Syntax problems when passing numerical integral into lsqcurvefit

3 views (last 30 days)
I am trying to fit an function which cannot be evaluated analytically. My script consists of a multitude of steps. (MATLAB 2013b)
Initalisation, 71024.mat contains among other variables V3 and Gzoomin:
clear all
close all
clc
filename='71024';
load(strcat(filename,'.mat'))
clc
syms V E
x = sym('x',[3,1]);
kB=1.38e-23;
delta1=200e-6;
T=.270;
xdata=V3(1:end-1);
ydata=Gzoomin;
Cn=1;
delta2=200e-6;
gamma2=10e-6;
As a second step, I want to evaluate this derivative analytically, and then turn it into a function handle.
Fun1 = x(1)*real(abs(E)/sqrt(E^2-delta1^2))*(diff(real((E+V-1i*x(3))/sqrt((E+V-1i*x(3))^2-x(2)^2)),V)*(1/(exp(E/(kB*T))+1)-1/(exp((E+V)/(kB*T))+1))-real((E+V-1i*x(3))/sqrt((E+V-1i*x(3))^2-x(2)^2))*diff(1/(exp((E+V)/(kB*T))+1),V));
Fun2 = matlabFunction (Fun1);
So far it's all fine. Fun2 depends on the following variables: E,V,x1,x2,x3 In the next step I want to integrate over E for given V,x1,x2,x3. V corresponds to xdata, x1,x2,x3 are the fit parameters. Note that this function can not be integrated analytically.
x0=[Cn delta2 gamma2];
x= lsqcurvefit(integral(@(E)Fun2,-Inf,Inf), x0,xdata, ydata);
This gives the following error:
Error using integralCalc/finalInputChecks (line 512)
Input function must return 'double' or 'single' values. Found 'function_handle'.
Error in integralCalc/iterateScalarValued (line 316)
finalInputChecks(x,fx);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 104)
[q,errbnd] = vadapt(@minusInfToInfInvTransform,interval);
Error in integral (line 88)
Q = integralCalc(fun,a,b,opstruct);
How can i solve this problem? Thank you in advance.

Answers (1)

Walter Roberson
Walter Roberson on 29 May 2015
What you pass to be fitted needs to be a function. You are passing integral() of something, so you are expecting integral() to return a function. But integral() is a numeric integrator and cannot return a function. You need another layer which does symbolic integration and does a matlabFunction() on that result.
I did see your remark about the integral not being analytic. I do not have the symbolic toolbox so I do not know whether it is able to convert unevaluated integrals into numeric integrals.
Now as to why integral() is what complained: you tried to use
integral(@(E)Fun2,-Inf,Inf)
@(E)Fun2 designates an anonymous function that expects one input argument and ignores that argument and always returns Fun2. But Fun2 is a function handle. If you want to evaluate Fun2 at a specific value then you need to pass in the appropriate parameters, such as
integral(@(E)Fun2(E,xdata,x1,x2,x3),-Inf,Inf)
Here, x1, x2, x3 need to have some value. In the general case, it does not matter what data type (numeric, symbolic, cell, struct) gets passed in: integral() doesn't care. But the function called upon (Fun2) needs to be able to process whatever is passed in, in a way that results in that function returning a specific numeric result for integral() to process. And there you have a problem, as you want the integral to return a formula so you can fit it.
So... you write something like
helper = @(x,xdata) integral(@(E) Fun2(E,xdata,x(1),x(2),x(3)),-Inf,Inf);
x = lsqcurvefit(helper, x0, xdata, ydata);
and there, you are passing in a function handle to lsqcurvefit(), not an integral. The function handle takes the given parameter and does a specific integral with them, returning the numeric result that will be matched against ydata.
Note: This particular formulation will fail if your ydata is not a scalar! It also assumes that xdata as a whole needs to be passed to the integral. If your setup were that you wanted each row of xdata to correspond to one value in the column vector ydata, then this code would need to be adjusted.
  1 Comment
Bas van 't Hooft
Bas van 't Hooft on 29 May 2015
Thank you for your quick response and clear explanation. Altough I think we are on the right track, this sadly does not completely solve the problem. The error I receive is the following:
Error using mupadmex
Error in MuPAD command: Array sizes must match.
Error in sym/privBinaryOp (line 1506)
Csym = mupadmex(op,args{1}.s, args{2}.s, varargin{:});
Error in sym/plus (line 7)
X = privBinaryOp(A, B, 'symobj::zip', '_plus');
Error in C:\Program
Files\MATLAB\R2012b\toolbox\symbolic\symbolic\symengine.p>makeFhandle/@(E,V,x1,x2,x3)-x1.*real(abs(E).*1.0./sqrt(E.^2-4.0e-8)).*((1.0./(exp(E.*2.683843263553408e23)+1.0)-1.0./(exp(E.*2.683843263553408e23+V.*2.683843263553408e23)+1.0)).*(real(1.0./((E+V-x3.*1i).^2-x2.^2).^(3.0./2.0).*(E.*2.0+V.*2.0-x3.*2.0i).*(E+V-x3.*1i)).*(1.0./2.0)-1.0./sqrt(abs(-(E+V-x3.*1i).^2+x2.^2)).*cos((log(((E+V-x3.*1i).^2-x2.^2)./abs(-(E+V-x3.*1i).^2+x2.^2)).*-1i).*(1.0./2.0)))-exp(E.*2.683843263553408e23+V.*2.683843263553408e23).*real(1.0./sqrt((E+V-x3.*1i).^2-x2.^2).*(E+V-x3.*1i)).*1.0./(exp(E.*2.683843263553408e23+V.*2.683843263553408e23)+1.0).^2.*2.683843263553408e23)
Error in @(E)Fun2(E,xdata,x(1),x(2),x(3))
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 104)
[q,errbnd] = vadapt(@minusInfToInfInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);
Error in @(x,xdata)integral(@(E)Fun2(E,xdata,x(1),x(2),x(3)),-Inf,Inf)
Error in lsqcurvefit (line 195)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT
cannot continue.
I guess this might be caused by the fact that in Fun1 x(1),x(2),x(3) are replaced by x1,x2,x3. Could this cause this error? How do I prevent this from happening?

Sign in to comment.

Products

Community Treasure Hunt

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

Start Hunting!