lsqcurvefit with a 'zero' in denominator

1 view (last 30 days)
Hello Everyone,
I have a data set [xdata,ydata], which are in fact calculated by a Fortran code. All I want to do is to fit these data into a specific nonlinear function. I have a clear definition of how this specific nonlinear function should be, and therefore I am trying to fit into that.
However, in order to try lsqcurvefit for a easier case, I used;
xdata=linspace(0,3,1000)
ydata=trip(xdata)
where trip is
tripl=1+xdata+xdata.^2+2*xdata.^3+153*xdata.^4-100*xdata.^5+(5-xdata).^-1;
Nonlinear function to be fitted is
function ftripl=ftrip(b,x)
ftripl=b(1)+b(2)*x+b(3)*x.^2+b(4)*x.^3+b(5)*x.^4+b(6)*x.^5+(b(7)-x).^-1;
end
I create initial parameters via
guess=4*rand(1,7)-2;
and run
fit=lsqcurvefit(@ftrip,guess,xdata,ydata);
I get decent values for all coefficients save b(7), which should attain the value 5. I recieve b(7)=1.02 with warning 'local minimum is possible'. How can I overcome this problem and find the value I require?
PS. In reality I will fit my data into a function of 5th order polynomial plus arctangent(a/(x-b)) where a,b and five coefficients of the polynomial will be found and x-b becomes very close to zero frequently.
  2 Comments
the cyclist
the cyclist on 7 Mar 2013
Edited: the cyclist on 7 Mar 2013
@Batuhan,
I edited your question to format the code, but I am not 100% certain that I got your definition of trip exactly right, because you had written
trip = trip1 = ...
and I was not quite sure what you meant there. Please check to see if I interpreted it correctly. Sorry if I messed up your intention.
Maybe even better would be to express trip as an anonymous function:
trip = @(x) 1+x+x.^2+2*x.^3+153*x.^4-100*x.^5+(5-x).^-1;
and then
y = trip(xdata);
Batuhan
Batuhan on 7 Mar 2013
@the cyclist
No, you are right, I made a mistake there. trip = @(x) 1+x+x.^2+2*x.^3+153*x.^4-100*x.^5+(5-x).^-1;
would be the correct one. Thank you.

Sign in to comment.

Accepted Answer

Matt J
Matt J on 7 Mar 2013
Edited: Matt J on 7 Mar 2013
In reality I will fit my data into a function of 5th order polynomial plus arctangent(a/(x-b)) where a,b and five coefficients of the polynomial will be found and x-b becomes very close to zero frequently.
If x-b is near zero at most data points x, you should probably just replace the arctangent term by pi/2*sign(a) and fit the remaining polynomial terms based on those data points only (using POLYFIT, of course, not LSQCURVEFIT). You can try each of the 3 possibilities for sign(a) and see which gives you the best fit.
If you want a good fit to the arctangent term, you'll need more data points away from the singularity.
  1 Comment
Matt J
Matt J on 7 Mar 2013
Edited: Matt J on 7 Mar 2013
If you want a good fit to the arctangent term, you'll need more data points away from the singularity.
As a compromise, after you've fit the polynomial terms b1...b6, you could also try obtaining a and b from the arctan term by doing
p=@(x) b(1)+b(2)*x+b(3)*x.^2+b(4)*x.^3+b(5)*x.^4+b(6)*x.^5 ;
zdata= tan(ydata - p(xdata));
A=[ones(length(zdata),1), zdata(:)];
B=zdata(:).*xdata(:);
ab=A\B;
a=ab(1);
b=ab(2);

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!