Solving a system of equations using a specific initial guess in Matlab - 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);

Related

matlab plot vectors must be the same lengths

I am writing a program regarding solving the following boundary value problem using shooting-bisection method:
y''-y+x=0, y(0)=y(1)=0.
I first convert this to a system of first order equations, set
y'=z
then I let dydt represent the vector (y',z'), and come up with the script file:
function dydt=shoot(t,y)
dydt=[y(2);y(1)-t]
end
With this, I then came up with the following code:
clear
clc
a=0;
b=1;
alpha=0;
beta=0;
s(1)=(beta-alpha)/(b-a);
s(2)=-1
[G,Y]=ode113('shoot',[a b],[alpha;s(1)]);
[G,Z]=ode113('shoot',[a b],[alpha;s(2)])
hold
tol=1e-4
u=s(1);
v=s(2);
while abs(u-v)>tol;
s(3)=(u+v)/2;
[G,W]=ode113('shoot',[a b],[alpha;s(3)]);
if W(end,1)>0
u=s(3);
else
v=s(3);
end
end
[G,W]=ode113('shoot',[a b],[alpha;s(3)])
plot(G,Y(:,1),'-o', G,Z(:,1),'-o',G,W(:,1),'-o')
Then I run the program, MATLAB said I'm using the plot argument incorrectly, where plot vectors must be the same lengths. I have no idea how to fix this problem. Any help is appreciated.
Your Y, Z and W outputs are from different runs of ode113. The output independents variables, G from each run are different because ode113 is an adaptive solver. There are two ways you can fix this. You can save your G outputs as separate variables:
...
[Gy,Y]=ode113('shoot',[a b],[alpha;s(1)]);
[Gz,Z]=ode113('shoot',[a b],[alpha;s(2)]);
...
[Gw,W]=ode113('shoot',[a b],[alpha;s(3)]);
plot(Gy,Y(:,1),'-o', Gz,Z(:,1),'-o',Gw,W(:,1),'-o');
Or you could specify a fixed set of output points by specifying more than two points for tspan (second argument to ode113):
...
tspan = linspace(a,b,50);
[G,Y]=ode113('shoot',tspan,[alpha;s(1)]);
[G,Z]=ode113('shoot',tspan,[alpha;s(2)]);
...
[G,W]=ode113('shoot',tspan,[alpha;s(3)]);
plot(G,Y(:,1),'-o', G,Z(:,1),'-o',G,W(:,1),'-o');
Unless your version of Matlab is more than 10 years old, you should also specify your integration function, shoot, via a function handle, not a string, i.e.:
[Gw,W]=ode113(#shoot,[a b],[alpha;s(3)]);

Unable to code non linear equation in MATLAB R2013a - MATLAB giving warning message

I wanted to solve the following equation in MATLAB R2013a using the Symbolic Math Toolbox.
(y/x)-(((1+r)^n)-1)/r=0 where y,x and n>3 are given and r is the dependent variable
I tried myself & coded as follows:
f=solve('(y/x)-(((1+r)^n)-1)/r','r')
but as the solution for r is not exact i.e. it is converging on successive iterations hence MATLAB is giving a warning output with the message
Warning: Explicit solution could not be found.
f =
[ empty sym ]
How do I code this?
There are an infinite number of solutions to this for an unspecified value of n > 3 and unknown r. I hope that it's pretty clear why – it's effectively asking for a greater and greater number of roots of (1+r)^n. You can find solutions for fixed values of n, however. Note that as n becomes larger there are more and more solutions and of course some of them are complex. I'm going to assume that you're only interested in real values of r. You can use solve and symbolic math for n = 4, n = 5, and n = 6 (for n = 6, the solution may not be in a convenient form):
y = 441361;
x = 66990;
n = 5;
syms r;
rsol = solve(y/x-((1+r)^n-1)/r==0,r,'IgnoreAnalyticConstraints',true)
double(rsol)
However, the question is "do you need all the solutions or just a particular solution for a given value of n"? If you just need a particular solution, you shouldn't be using symbolic math at all as it's slower and has practical issues like the ones you're experiencing. You can instead just use a numerical approach to find a zero of the equation that is near a specified initial guess. fzero is the standard function for solving this sort of problem in a single variable:
y = 441361;
x = 66990;
n = 5;
f = #(r)y/x-((1+r).^n-1)./r;
r0 = 1;
rsol = fzero(f,r0)
You'll see that the value returned is the same as one of the solutions from the symbolic solution above. If you adjust the initial guess r0 (say r0 = -3), it will return the other solution. When using numeric approaches in cases when there are multiple solutions, if you want specific solutions you'll need to know about the behavior of your function and you'll need to add some clever extra code to choose initial guesses.
I think you forgot to define n as well.
f=solve('(y/x)-(((1+r)^n)-1)/r=0','n-3>0','r','n')
Should solve your problem :)

Using nlinfit in Matlab?

I'm having trouble understanding and applying the use of nlinfit function in Matlab. So, let's say I'm given vectors
x = [1, 2, 3, 4, 5]
y = [2.3, 2.1, 1.7, .95, .70]
and I'm asked to fit this data to an exponential form (I don't know if the numbers will work, I made them up) where y = A*e^(Bx) + C (A/B/C are constants).
My understanding is that nlinfit takes 4 arguments, the two vectors, a modelfunction which in this case should be the equation I have above, and then beta0, which I don't understand at all. My question is how do you implement the modelfunction in nlinft, and how do you find beta0 (when only working with 2 vectors you want to plot/fit) and how should it be implemented? Can someone show me an example so that I can apply this function for any fit? I suspect I'll be using this a lot in the future and really want to learn it.
Check out the second example in the docs: http://www.mathworks.com/help/stats/nlinfit.html
Basically you pass a function handle as your modelfunction parameter. Either make a function in a file and then just pass it the function name with an # in front or else make an anonymous function like this:
nlinfit(x, y, #(b,x)(b(1).*exp(b(2).*x) + b(3)), beta0)
You'll notice that in the above I have stuck all your parameters into a single vector. The first parameter of your function must be a vector of all the points you are trying to solve for (i.e. A, B and C in your case) and the second must be x.
As woodchips has said beta0 is your starting point so your best guess (doesn't have to be great) of your A, B and C parameters. so something like [1 1 1] or rand(3,1), it is very problem specific though. You should play around with a few. Just remember that this is a local search function and thus can get stuck on local optima so your starting points can actually be quite important.
beta0 is your initial guess at the parameters. The better your guess, the more likely you will see convergence to a viable solution. nlinfit is no more than an optimization. It has to start somewhere.

Function works with lsqcurvefit but not nlinfit

I'm attempting to get a nonlinear least squares fit for the following function:
Nloc = 250;
d = 1 / Nloc;
m = 0.5; %Initial guess
ncmfun = #(m, p) arrayfun(#(p) betainc(d, Nloc*m .* p, Nloc*m .* (1 - p), 'upper'), p);
Where m is the parameter being fit, Nloc and d are constants, and p and freq are vectors of positive real numbers and of the same length (I triple checked). When I use lsqcurvefit everything works fine:
[mfit,resnorm,] = lsqcurvefit(ncmfun, m, p, freq, 0, 1)
Also, if I use any m to evaluate the function, everything works fine as well. However when I use nlinfit:
[mfit,R,Jac,CovB,MSE,ErrorModelInfo] = nlinfit(p, freq, ncmfun, m)
I get the following error(s):
Error using betainc
Z must be real and non-negative.
Error in #(p)betainc(d,Nloc*m.*p,Nloc*m.*(1-p),'upper')
Error in
#(m,p)arrayfun(#(p)betainc(d,Nloc*m.*p,Nloc*m.*(1-p),'upper'),p)
Error in nlinfit>#(b,x)w.*model(b,x) (line 206)
modelw = #(b,x) w.*model(b,x);
Error in nlinfit>LMfit (line 486)
yfit = model(beta,X);
Error in nlinfit (line 207)
[beta,J,~,cause,fullr] = LMfit(X,yw,
modelw,beta,options,verbose,maxiter);
Error in Sloan_NCM_Parameterize_Nm (line 37)
[mfit,R,Jac,CovB,MSE,ErrorModelInfo] = nlinfit(p, freq,
ncmfun, m);
What's especially frustrating was this same script was working a couple weeks ago. I then tried to use it again and it no longer works. I tried to go through and see if I accidentally changed something and didn't remember, but I can't find any errors. Furthermore, I'm confused as to why lsqcurvefit works but not nlinfit. I'd like to use nlinfit because it provides me with more statistical information about the error.
Thanks in advance for any help you can provide!
They both use the same algorithm to identify a solution, however, you are explicitly stating an upper and lower bound for your solution in lsqcurvefit which ensures your incomplete beta function behaves. You don't have this option in nlinfit. I'm not sure what you did before (you can always look at the command history)
You have a few options from this point:
1 - programatically intercept every value that goes to ncmfun, by either expending your anonymous functions in what my nightmares are made of, or creating your own m-file for it. If the value is outside of [0,1] return progressively higher error value (with the boundaries being >>> then any possible value within the set)
2 - Try to force a quicker convergence by playing with some of the parameters (perhaps by using a robust fitting option (cf documentation))

Error in Ordinary Differential Equation representation

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.