Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Nlinfit with a symbolic expression

38 views
Skip to first unread message

Juan

unread,
Feb 13, 2012, 9:33:11 AM2/13/12
to
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:

q = subs ( q, {a,b,c}, {sym('p(1)'),sym('p(2)'),sym('p(3)')} );
func = inline( vectorize (char(q)), 'p','t' )

% 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.

I am certainly not defining my fitting function in the appropriate manner, but I cannot find the error. Any help will be appreciated

Thank you in advance

John.

Steven_Lord

unread,
Feb 13, 2012, 10:26:59 AM2/13/12
to


"Juan " <then...@yahoo.com> wrote in message
news:jhb6v6$8pl$1...@newscl01ah.mathworks.com...
> 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:
>
> q = subs ( q, {a,b,c}, {sym('p(1)'),sym('p(2)'),sym('p(3)')} );
> func = inline( vectorize (char(q)), 'p','t' )
>
> % 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

Juan

unread,
Feb 14, 2012, 10:04:49 AM2/14/12
to
> 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.

Steven_Lord

unread,
Feb 14, 2012, 12:18:32 PM2/14/12
to


"Juan " <then...@yahoo.com> wrote in message
news:jhdt6h$b5s$1...@newscl01ah.mathworks.com...
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:

http://www.mathworks.com/help/toolbox/stats/nlinfit.html

"Function specified using @ that accepts two arguments:

A coefficient vector, say b

The array X"

So instead of trying to pass in q or @q, do this:

myfun = @(b, x) q(b(1), b(2), b(3), x);
[ahat, r, l, cov, mse] = nlinfit(y, x, p, myfun);

Now myfun presents to NLINFIT the interface it expects (a two-input
interface) and calls q using the interface it expects (a four-input
interface.)
0 new messages