Error in Ordinary Differential Equation representation - matlab

UPDATE
I am trying to find the Lyapunov Exponents given in link LE. I am trying to figure it out and understand it by taking the following eqs for my case. These are a set of ordinary differential equations (these are just for testing how to work with cos and sin as ODE)
f(1)=ALPHA*(y-x);
f(2)=x*(R-z)-y;
f(3) = 10*cos(x);
and x=X(1); y=X(2); cos(y)=X(3);
f1 means dx/dt;f2 dy/dt and f3 in this case would be -10sinx. However,when expressing as x=X(1);y=X(2);i am unsure how to express for cos.This is just a trial example i was doing so as to know how to work with equations where we have a cos,sin etc terms as a function of another variable.
When using ode45 to solve these Eqs
[T,Res]=sol(3,#test_eq,#ode45,0,0.01,20,[7 2 100 ],10);
it throws the following error
??? Attempted to access (2); index must be a positive integer or logical.
Error in ==> Eq at 19
x=X(1); y=X(2); cos(x)=X(3);
Is my representation x=X(1); y=X(2); cos(y)=X(3); alright?
How to resolve the error?
Thank you

No your representation is completely wrong.
You can't possibly set values in this way!
For a start, you are trying to assign a value X(3) to a function.
first I am not sure you understand the difference between
x=4
and
4=x
which are completely different meanings. If you understand this, you'll see that you can't possibly assign using cos(x)=X(3).
Second: what is the function sol() you are calling? have you defined it?
Third, to solve or evaluate ODEs you should be using deval or solve functions in matlab. Their help files should give you examples.

Related

Is there an inverse factorial expression I can use in Matlab?

I want to edit this to get numberOfCircuits on its own on the left. Is there a possible way to do this in MATLAB?
e1=power(offeredTraffic,numberOfCircuits)/factorial(numberOfCircuits)/sum
The math for this problem is given in https://math.stackexchange.com/questions/61755/is-there-a-way-to-solve-for-an-unknown-in-a-factorial, but it's unclear how to do this with Matlab's functionality.
I'm guessing the easy part is rearranging:
fact_to_invert = power(offeredTraffic,numberOfCircuits)/sum/e1;
Inverting can be done, for instance, by using fzero. First define a continuous factorial based on the gamma function:
fact = #(n) gamma(n+1);
Then use fzero to invert it numerically:
numberOfCircuits_from_inverse = fzero(#(x) fact(x)-fact_to_invert,1);
Of course you should round the result for safe measure, and if it's not an integer then something's wrong.
Note: it's very bad practice (and brings 7 years bad luck) to name a variable with a name which is also a built-in, such as sum in your example.

MATLAB: using a minimum function within symsum

I am trying to run code similar to the following, I replaced the function I had with one much smaller, to provide a minimum working example:
clear
syms k m
n=2;
symsum(symsum(k*m,m,0,min(k,n-k)),k,0,n)
I receive the following error message:
"Error using sym/min (line 86)
Input arguments must be convertible to floating-point numbers."
I think this means that the min function cannot be used with symbolic arguments. However, I was hoping that MATLAB would be substituting in actual numbers through its iterations of k=0:n.
Is there a way to get this to work? Any help much appreciated. So far I the most relevant page I found was here, but I am somewhat hesitant as I find it difficult to understand what this function does.
EDIT following #horchler, I messed around putting it in various places to try and make it work, and this one did:
clear
syms k m
n=2;
symsum(symsum(k*m,m,0,feval(symengine, 'min', k,n-k)),k,0,n)
Because I do not really understand this feval function, I was curious to whether there was a better, perhaps more commonly-used solution. Although it is a different function, there are many pieces online advising against the eval function, for example. I thought perhaps this one may also carry issues.
I agree that Matlab should be able to solve this as you expect, even though the documentation is clear that it won't.
Why the issue occurs
The problem is due the inner symbolic summation, and the min function itself, being evaluated first:
symsum(k*m,m,0,min(k,n-k))
In this case, the input arguments to sym/min are not "convertible to floating-point numbers" as k is a symbolic variable. It is only after you wrap the above in another symbolic summation that k becomes clearly defined and could conceivably be reduced to numbers, but the inner expression has already generated an error so it's too late.
I think that it's a poor choice for sym/min to return an error. Rather, it should just return itself. This is what the sym/int function does when it can't evaluate an integral symbolically or numerically. MuPAD (see below) and Mathematica 10 also do something like this as well for their min functions.
About the workaround
This directly calls a MuPAD's min function. Calling MuPAD functions from Matlab is discussed in more detail in this article from The MathWorks.
If you like, you can wrap it in a function or an anonymous function to make calling it cleaner, e.g.:
symmin = #(x,y)feval(symengine,'min',x,y);
Then, you code would simply be:
syms k m
n = 2;
symsum(symsum(k*m,m,0,symmin(k,n-k)),k,0,n)
If you look at the code for sym/min in the Symbolic Math toolbox (type edit sym/min in your Command Window), you'll see that it's based on a different function: symobj::maxmin. I don't know why it doesn't just call MuPAD's min, other than performance reasons perhaps. You might consider filing a service request with The MathWorks to ask about this issue.

Issue with Matlab solve function?

The following command
syms x real;
f = #(x) log(x^2)*exp(-1/(x^2));
fp(x) = diff(f(x),x);
fpp(x) = diff(fp(x),x);
and
solve(fpp(x)>0,x,'Real',true)
return the result
solve([0.0 < (8.0*exp(-1.0/x^2))/x^4 - (2.0*exp(-1.0/x^2))/x^2 -
(6.0*log(x^2)*exp(-1.0/x^2))/x^4 + (4.0*log(x^2)*exp(-1.0/x^2))/x^6],
[x == RD_NINF..RD_INF])
which is not what I expect.
The first question: Is it possible to force Matlab's solve to return the set of all solutions?
(This is related to this question.) Moreover, when I try to solve the equation
solve(fpp(x)==0,x,'Real',true)
which returns
ans =
-1.5056100417680902125994180096313
I am not satisfied since all solutions are not returned (they are approximately -1.5056, 1.5056, -0.5663 and 0.5663 obtained from WolframAlpha).
I know that vpasolve with some initial guess can handle this. But, I have no idea how I can generally find initial guessed values to obtain all solutions, which is my second question.
Other solutions or suggestions for solving these problems are welcomed.
As I indicated in my comment above, sym/solve is primarily meant to solve for analytic solutions of equations. When this fails, it tries to find a numeric solution. Some equations can have an infinite number of numeric solutions (e.g., periodic equations), and thus, as per the documentation: "The numeric solver does not try to find all numeric solutions for [the] equation. Instead, it returns only the first solution that it finds."
However, one can access the features of MuPAD from within Matlab. MuPAD's numeric::solve function has several additional capabilities. In particular is the 'AllRealRoots' option. In your case:
syms x real;
f = #(x)log(x^2)*exp(-1/(x^2));
fp(x) = diff(f(x),x);
fpp(x) = diff(fp(x),x);
s = feval(symengine,'numeric::solve',fpp(x)==0,x,'AllRealRoots')
which returns
s =
[ -1.5056102995536617698689500437312, -0.56633904710786569620564475006904, 0.56633904710786569620564475006904, 1.5056102995536617698689500437312]
as well as a warning message.
My answer to this question provides other way that various MuPAD solvers can be used, particularly if you can isolate and bracket your roots.
The above is not going to directly help with your inequalities other than telling you where the function changes sign. For those you could try:
s = feval(symengine,'solve',fpp(x)>0,x,'Real')
which returns
s =
(Dom::Interval(0, Inf) union Dom::Interval(-Inf, 0)) intersect solve(0 < 2*log(x^2) - 3*x^2*log(x^2) + 4*x^2 - x^4, x, Real)
Try plotting this function along with fpp.
While this is not a bug per se, The MathWorks still might be interested in this difference in behavior and poor performance of sym/solve (and the underlying symobj::solvefull) relative to MuPAD's solve. File a bug report if you like. For the life of me I don't understand why they can't better unify these parts of Matlab. The separation makes not sense from the perspective of a user.

Solving a system of equations using a specific initial guess in Matlab

I have a question about solving a system of equations and initial guesses of the solution. I want to solve a system of equations where "x", a Tx1 vector, are my unknowns, "a" a Tx1 vector and "B" a TxT matrix. "f" is the function I want to solve for. I want to solve for "x" such that "f==0":
x = sym('x', [T,1]);
f = -x+1-(1+erf((a - B*x)./sqrt(2)))/2; % -x+1-normcdf(a-B*x)
Spp = solve(f==0, x);
I use Matlab's solve (or vpasolve) functions to obtain values. If the entries of "B" are above a certain value I should observe a jump for changing values of "a" (which I do). However, depending on the initial guess of the solution, i.e. for example either the initial guess is 1 or 0, the position of the jump occurs at different values for "a", a hysteresis cycle occurs.
I solved the equation using fzero for T=1. I specified the initial guess and indeed was able to observe the hysteresis cycle. For T>1, fzero does not work anymore and I tried solve as well as vpasolve. solve does not allow initial guesses and for vpasolve I even get with examples from Matlab's help site an error whenever I include more than the system of equations and the unknown variables, i.e. vpasolve(eqn,var) works fine but for vpasolve(eqn,var,init_guess) I get the following error:
Error using getEqnsVars (line 50) Expecting two arguments: a vector of
equations and a vector of variables.
Error in sym/vpasolve (line 91) [eqns,vars] =
getEqnsVars(varargin{1:end-1});
What am I doing wrong? Is there another function I could try?
Edit: I didn't use 'fsolve' but 'fzero' to find the roots.
You can use slightly different definition of function f and try fsolve. Here you don't have to explicitly define x as symbolic variables.
f = #(x) -x+1-(1+erf((a - B*x)./sqrt(2)))/2; % -x+1-normcdf(a-B*x)
initial_guess = zeros(T,1);
Spp = fsolve(f,initial_guess);

Solving Bessel Function using Runge Kutta

I'm working on an assignment for a class of mine and I'm supposed to write a code using a program of my choice (I've chosen Matlab) to solve the Bessel function differential equation using the 4th order Runge-Kutta method. For reference the Bessel function DE is:
x^2*(J_n)''+x*(J_n)'+(x^2-n^2)*J_n=0.
I'm able to separate this into two coupled first order DEs by:
(J_n)'=Z_n and
(Z_n)'+(1/x)*Z_n+[(x^2-n^2)/x^2]*J_n=0.
I have no experience with Matlab nor any other programming language before this assignment. I know Matlab has the 'ode45' command but I'm supposed to write the code myself, not rely on Matlab's commands. So far I've been working on the n=0 case for the Bessel function but I keep getting an error when I try and plot the function. The current error I have says: "Undefined function or method 'J' for input arguments of type 'double'." But I don't know how to fix this error nor if my code is even correct. Could someone tell me where I've gone wrong or what is the correct way to write this code?
h=0.01; %step size
J_0(1)=1; %initial condition for J_0
Z_0(1)=1; %initial condition for Z_0-This value should be zero
%but Matlab gives me an error. To fix this, I input
%Z_0(1)-1 to use the correct value for Z_0(1).
x(1)=0.001; %first value of x
dZ(Z_0,J_0)=(-1/x)*(Z_0-1)-J_0;
for i=[1:1:10]
dZ1=(-1/x)*(Z_0-1)-J_0;
dJ1=(Z_0(1)-1)*h;
dZ2=(-1/x)*(Z_0-1+0.5*h)-(J_0+0.5*h*dJ1);
dJ2=((Z_0(1)-1)+dZ1)*h;
dZ3=(-1/x)*(Z_0-1+0.5*h)-(J_0+0.5*h*dJ2);
dJ3=((Z_0(1)-1)+dZ1+dZ2)*h;
dZ4=(-1/x)*(Z_0-1+h)-(J_0+h*dJ3);
dJ4=((Z_0(1)-1)+dZ1+dZ2+dZ3)*h;
J(i+1)=J(i)+(h/6)*(dJ1+2*dJ2+2*dJ3+dJ4);
end
plot(J_0);
Thanks in advance for any help
Your problem is on the line:
J(i+1)=J(i)+(h/6)*(dJ1+2*dJ2+2*dJ3+dJ4);
In the right-hand side of your assignment operator you use the variable J that is never set before i is taking the value 1. Looks like a typo to me (should it be J_0 instead?)
Also, don't forget your index i when computing your dJ and dZ stuff in the for loop.