Hi everyone,
I am trying to fit a set of data (t,y) to a function given by a definite integral which matlab cannot find explicitly. I start defining a symbolic expression, given by a definite integral of a function ‘f’:
syms a b c t x; f=a*exp (-((log (x)-log (b))/c)^2)*exp (-x*t)
q= int(f,x,0,Inf)
% where ‘a’, ‘b’ and ‘c’ are parameters.
% Next I convert it to an inline function rather than a symbolic expression:
> Hi everyone,
> I am trying to fit a set of data (t,y) to a function given by a definite > integral which matlab cannot find explicitly. I start defining a symbolic > expression, given by a definite integral of a function ‘f’:
> syms a b c t x; f=a*exp (-((log (x)-log (b))/c)^2)*exp (-x*t)
> q= int(f,x,0,Inf)
> % where ‘a’, ‘b’ and ‘c’ are parameters.
> % Next I convert it to an inline function rather than a symbolic > expression:
> % Then I introduce the data I want to fit:
> t=time;
> y=counts;
> % Introduce some initial values:
> p0=[320,0.55,0];
> % And finally try to perform a nonlinear fit:
> [ahat,r,J,cov,mse]=nlinfit(t,y,func,p0)
> But I get the error message:
> Error evaluating inline model function.
> Error in inline expression.
Check your q. Are you certain that INT was able to compute the integral of your function? It may be able to if you set certain assumptions on b, c, and t (I haven't tried this) but without those assumptions I don't think it can.
In this case, I would avoid symbolic processing altogether. Since you want to fit numerically, integrate numerically with QUADGK. Write a function that accepts the coefficients a, b, c, and t and calls QUADGK once for each element of the x input to return the value of the integral.
-- Steve Lord
sl...@mathworks.com
To contact Technical Support use the Contact Us link on http://www.mathworks.com
> Check your q. Are you certain that INT was able to compute the integral of > your function? It may be able to if you set certain assumptions on b, c, and > t (I haven't tried this) but without those assumptions I don't think it can.
> In this case, I would avoid symbolic processing altogether. Since you want > to fit numerically, integrate numerically with QUADGK. Write a function that > accepts the coefficients a, b, c, and t and calls QUADGK once for each > element of the x input to return the value of the integral.
> -- > Steve Lord
Thank you for your time Steve.
I have changed my approach by using ‘quadgk’ as you suggest. My data consist of a dependent (y) and independent variables (x). Then I have three parameters which I want to retrieve from my data fit (a,b,c). I start by defining my fitting function (an integral) in a separate .m file. The variable of integration is ‘t’:
function f=q(a,b,c,x)
f = zeros(size(x));
for j=1:numel(x)
f(j) = quadgk(@(t) a*exp (-((log (x)-log (b))/c)^2)*exp (-x*t),0,Inf);
end
Then I try to perform the fit using the function ‘q’:
clear all
clc
load time.dat
load counts.dat
x=time;
y=counts;
q;
p=[a,b,c];
p0=[320,0.55,2];
[ahat,r,J,cov,mse]=nlinfit(y,x,p,q);
ahat
But it seems Matlab does not recognize the x variable when I call ‘q’. I get: ??? Input argument "x" is undefined.
>> Check your q. Are you certain that INT was able to compute the integral >> of your function? It may be able to if you set certain assumptions on b, >> c, and t (I haven't tried this) but without those assumptions I don't >> think it can.
>> In this case, I would avoid symbolic processing altogether. Since you >> want to fit numerically, integrate numerically with QUADGK. Write a >> function that accepts the coefficients a, b, c, and t and calls QUADGK >> once for each element of the x input to return the value of the integral.
>> -- >> Steve Lord
> Thank you for your time Steve.
> I have changed my approach by using ‘quadgk’ as you suggest. My data > consist of a dependent (y) and independent variables (x). Then I have > three parameters which I want to retrieve from my data fit (a,b,c). I > start by defining my fitting function (an integral) in a separate .m file. > The variable of integration is ‘t’:
> function f=q(a,b,c,x)
> f = zeros(size(x));
> for j=1:numel(x)
> f(j) = quadgk(@(t) a*exp (-((log (x)-log (b))/c)^2)*exp (-x*t),0,Inf);
> end
> Then I try to perform the fit using the function ‘q’:
> clear all
> clc
> load time.dat
> load counts.dat
Don't "poof" variables into your workspace like that. Call LOAD with an output argument and refer to the fields of those struct arrays instead.
> x=time;
> y=counts;
> q;
> p=[a,b,c];
> p0=[320,0.55,2];
> [ahat,r,J,cov,mse]=nlinfit(y,x,p,q);
This won't work for two reasons. First, this attempts to call q with zero input arguments and pass the output of that call into NLINFIT as the fourth input. Even if you replaced that with @q it still wouldn't work.
You will need to specify the fun input argument using an anonymous function adapter, since NLINFIT requires the function that you pass to it be a: