Matlab :Model fitting and optimization error - matlab

I have a defined values of input (time samples) output (concentration), I would like to fit a model in order to estimate the Parameter values of rate constants(here in this case rate constants were defined as K1 K2 K3)
I have used lsqcurvefit for optimization but i am incurring errors in my usage of lsqcurvefit solver
First the values of x variable(t) and y variable(c_tot)
c_tot =[0,0,0,396.979609003375,503.769614648079,285.408414510699,137.309948090421,...
63.0089145454838,28.2076980338446,12.4169874862731,5.39698687726493,...
2.32247111168307,0.971427824475975,0.396298705702665,0.154518313562792,...
0.0563350826881436,0.0175309433420762,
0.00589400762862266,0.00199918527022414];%Loading Sampled Mat file values for fitting the Estimates of K in it
t=[0 0.25 0.5 0.75 1 1.5 2 3 4 9 13 18 23 28 33 38 43 48 53];%time samples
now the model which needs to be fitted
%-----------Model to be fitted-------------------------------------
k1_r=0.014;%reference tissue rate constant
a1=17501;a2=28500;a3=65000;%Values of a1 a2 a3 of Arterial input function
b1=0.9;b2=0.2;b3=0.5;%Values of b1 b2 b3 of Arterial Input Function
td=0.3% Indicates delay time
tmax=0.8% maximum peak time concentration
A = ((K(1)*K(2))/(k1_r*(K(2)+K(3))));
B = ((K(1)*K(3))/(k1_r*(K(2)+K(3))));
model=#(K,t)conv((a1 * exp(-b1 * (t - tmax))+...
a2 * exp(-b2 * (t - tmax))) +...
a3 * exp(-b3 * (t - tmax)),...
(A*exp(-(K(2)+K(3))*t+B)),'same');
Now i have used initial estimates of the parameters(k1 k2 k3) which i would like to fit
and called the solver
%----------------Assignment------------------------------------------------
K=[0.1 0.08 0.4];% Initial estimates of K1 K2 K3
%----------------Least-square curvefitting---------------------------------
K_est=lsqcurvefit(model,K,t,c_tot);
plot(K_est,'o');
xlabel('Time(mins)');
ylabel('Concentration(Bq/ml)');
Following is the error that i am incurring
Undefined function 'tomlablic' for input arguments of type 'double'.
Error in tomlabVersion (line 45)
[x1,x2,x3,x4,x5,x6,tomV,OS]=tomlablic(1);
Error in GetSolver (line 72)
[TomV,os,TV] = tomlabVersion;
Error in lsqnonlin (line 415)
Solver = GetSolver(checkType([],Prob.probType),...
Error in lsqcurvefit (line 298)
[x, f_k, r_k, ExitFlag, Output, Lambda, J_k, Result] =...
I am not experienced enough to know what I could do in order to perform model fitting.
Does any other solver will help me in this or is there any Global optimization tool box with which i can fit in initialized values
Any tips are welcome...

You are missing some TOMLAB files (looks very much like a missing license file).
Please make sure you have a complete installation of TOMLAB (which is sold by a company different from Mathworks) and try again.
As an alternative to TOMLAB, you can try Matlab's Global Optimization toolbox.

Related

Using Hindmarsh’s ODE solver LSODE in OCTAVE

I am learning OCTAVE, and I am trying to use LSODE ODE solver to integrate a version of FitzHugh–Nagumo model. My attempt looks like this:
time = linspace(0,200,1000);
u0 = rand(32,32);
v0 = rand(32,32);
vec_u0 = reshape(u0,[1,size(u0)(1)*size(u0)(2)]);
vec_v0 = reshape(v0,[1,size(v0)(1)*size(v0)(2)]);
vec_FHN0 = horzcat(vec_u0,vec_v0);
FHN = lsode("FHN_eq_vec", vec_FHN0, time);
FHN(end)
where all of the functions I have defined are in the repository I have set in GitHub - link. I have created a function that transform the two 2D fields of the FHN model into a row vector (as I understand from the examples here the LSODE integrator use row vector as input). I got this error message:
>> fhn_integrate_lsode
warning: non-integer range used as index
warning: called from
FHN_eq_vec at line 3 column 7
fhn_integrate_lsode at line 9 column 5
error: reshape: can't reshape 0x1 array to 1x1 array
error: called from
FHN_eq_vec at line 4 column 3
fhn_integrate_lsode at line 9 column 5
error: lsode: evaluation of user-supplied function failed
error: called from
fhn_integrate_lsode at line 9 column 5
error: lsode: inconsistent sizes for state and derivative vectors
error: called from
fhn_integrate_lsode at line 9 column 5
>>
Someone knows what could be the problem?
This has been answered at http://octave.1599824.n4.nabble.com/Using-Hindmarsh-s-ODE-solver-LSODE-in-OCTAVE-td4674210.html
However, looking quickly at your code, the system that you want to
solve is probably an ordinary differential equation stemming from a
pde space discretization, i.e.,
$dx(t)/dt = f(x,t) := -K x(t) + r(t)$
with K being a square matrix (Laplacian?!) and f a time-dependent
function of matching dimension. I expect that your system is stiff
(due to the negative Laplacian on the right-hand side) and that you
are happy with errors in the order of 10^(-4). Thus you should adapt
the options of lsode:
lsode_options("integration method","stiff");
lsode_options("absolute tolerance",1e-4);
lsode_options("relative tolerance",1e-4);
Then
T = 0:1e-2:1; % time vector
K = sprandsym(32,1)+eye(32); % symmetric stiffness matrix
x0 = rand(32,1); % initial values
r = #(t) rand(32,1)*sin(t); % excitation vector
f = #(x,t) (-K*x+r(t)); % right-hand-side function
x=lsode (f, x0, T); % get solution from lsode
You should exploit any knowledge on the Jacobian df/dx since this will
speed up computations. It's trivial in the case of linear ODE:
f = {#(x,t) -K*x+r(t), #(x,t) -K}; % right-hand-side function.
On the other hand, if the system has an additional mass matrix
$M dx(t)/dt = -K x(t) + r(t)$
things might become more complicated. You probably want to use another
time stepper. Only if M has full rank then you could do
f = #(x,t) ( M\(-K*x+r(t)) ); % right-hand-side function
which is typically not very efficient.
Bye Sebastian

how to get the f-statistic,p-value out of NonLinearModel in MATLAB 2013a

I use mdl=NonLinearModel.fit to fit a non-linear model.
How can I get the F-statistic and p-value from the result (line: "F-statistic vs. constant model")?
Example code:
load carsmall
X = Weight;
y = MPG;
modelfun = 'y ~ b1 + b2*exp(-b3*x/1000)';
beta0 = [1 1 1];
mdl=NonLinearModel.fit(X,y,modelfun,beta0)
which produces the following:
mdl =
Nonlinear regression model:
y ~ b1 + b2*exp( - b3*x/1000)
Estimated Coefficients:
Estimate SE tStat pValue
________ _______ ________ __________
b1 -17.725 31.321 -0.56594 0.57283
b2 77.862 21.332 3.6499 0.00043735
b3 0.21775 0.17176 1.2677 0.20814
Number of observations: 94, Error degrees of freedom: 91
Root Mean Squared Error: 4.12
R-Squared: 0.743, Adjusted R-Squared 0.738
F-statistic vs. constant model: 132, p-value = 1.34e-27
You're going to need [Fstat,pval]=fTest(mdl);
However this requires you to change permissions to public in a number of scripts. I just ran MATLAB as root and manually changed every permission to public in all files that were returning errors until I could actually get what I needed. It seems to work but there is probably a better way to do it.

Issue integrating inside ode45 loop

When I try to use this Matlab code it goes in an infinite loop. I am trying to perform integration inside ode45:
clear
clc
options = odeset('RelTol',1e-4,'AbsTol',[1e-4 1e-4 1e-5]);
[T,Y] = ode45(#rigid,[0 12],[0 1 1],options);
plot(T,Y(:,1),'+',T,Y(:,2),'*',T,Y(:,3),'.')
function dy = rigid(t,y)
dy = zeros(3,1); % a column vector
dy(1) = y(2) ;
dy(2) = -y(1) * y(3);
fun = #(t) exp(-t.^2).*log(t).^2+y(1);
q = integral(fun,0,Inf);
dy(3) = y(2) * y(3) + q;
There is no "infinite loop." Your function just takes a very long time to integrate. Try setting tspan to [0 1e-7]. It appears to be a high frequency oscillation, but I don't know if your equations are correct (that's a math question rather than a programming one). Such systems are hard to integrate accurately (ode15 might be a better choice), let alone quickly.
You also didn't bother to mention the important fact that the call to integral is generating a warning message:
Warning: Minimum step size reached near x = 1.75484e+22. There may be a
singularity, or the tolerances may be too tight for this problem.
> In funfun/private/integralCalc>checkSpacing at 457
In funfun/private/integralCalc>iterateScalarValued at 320
In funfun/private/integralCalc>vadapt at 133
In funfun/private/integralCalc at 84
In integral at 88
In rtest1>rigid at 17
In ode15s at 580
In rtest1 at 5
Printing out warning messages on each iteration greatly slows down integration. There's a good reason for this warning. You do realize that the function that you're evaluating with integral from 0 to Inf is equivalent to the following, right?
sqrt(pi)*((eulergamma + log(4))^2/8 + pi^2/16) + Inf*y(1)
where eulergamma is psi(1) or double(sym('eulergamma')). Your integrand doesn't converge.
If you like, can try to avoid the warning message in one of two ways.
1. Turn off the the warning (being sure to re-enable it afterwards). You can do that with the following code:
...
warning('OFF','MATLAB:integral:MinStepSize');
[T,Y] = ode45(#rigid,[0 12],[0 1 1],options);
warning('ON','MATLAB:integral:MinStepSize');
...
You can obtain the the ID for a waring via the lastwarn function.
2. The other option might be to change your integration bounds and avoid the warning altogether, e.g.:
...
q = integral(fun,0,1e20);
...
This may or may not be acceptable, but integral is not be returning the correct solution either because the result doesn't converge.

comparing MATLAB fmincon and ga (genetic algorithm) results: issue with ga

I have a fairly complex optimization problem set up that I've solved through fmincon by calling it like this
myfun = #(x5) 0.5 * (norm(C*x5 - d))^2 + 0.5 * (timeIntervalMeanGlobal * powerAbsMaxMaxGlobal * sum(x5(28:128),1))^2;
[x5, fval] = fmincon(myfun, initialGuess, -A, b, Aeq, beq, lb, []);
The components are far to long to print here, but here are the dimensions
C: 49 x 128
x5: 128 x 1
d: 49 x 1
timeIntervalMeanGlobal, powerAbsMaxMaxGlobal: constants
initialGuess: 128 x 1
A: 44541 x 128
b: 44541 x 1
Aeq: 24 x 128
beq: 24 x 1
lb: 128 x 1
This works in code, but I don't get results that I'm completely happy with. I'd like to compare it with the built in ga function in MATLAB, which is called in a similar way, but I get an error when I try to run it like this
[x5, fval] = ga(myfun, nvars, -A, b, Aeq, beq, lb, []);
where nvars = 128. There's a long list of about 8 errors starting with
??? Error using ==> mtimes
Inner matrix dimensions must agree.
and ending with
Caused by:
Failure in user-supplied fitness function evaluation. GA cannot continue.
Can someone please instruct me on how to call ga properly, and give insight on why this error might occur with the ga call when the same code doesn't cause an error with fmincon? I've tried all the MATLAB help files and examples with a few different permutations of this but no better luck. Thanks.
UPDATE: I think I found the problem but I don't know how to fix it. The ga documentation says "The fitness function should accept a row vector of length nvars". In my case, myfun is the fitness function, but x5 is a column vector (so is lb). So while mathematically I know that C*x5 = d is the same as x5'*C' = d' even for non-square matrices, I can't formulate the problem that way for the ga solver. I tried - it makes it past the fitness function but then I get the error
The number of rows in A must be the same as the length of b.
Any thoughts on how to get this problem in the right format for the solver? Thanks!
Got it! I just had to manipulate the fitness function to make it use x5 as a row vector even though it's a column vector in all the constraints
myfun = #(x5) 0.5 * (norm(x5 * C' - d'))^2 + 0.5 * (timeIntervalMeanGlobal * powerAbsMaxMaxGlobal * sum(x5(28:128)))^2;
Phew!

MATLAB how do I access a specific coefficient in a symbolic equation system solution?

I need to run a simple Monte Carlo varying coefficients on a system of equations. I need to record the solved coefficient of one of the variables each time.
The following gets me results from a single run:
syms alpha gamma Ps Pc beta lambda Pp Sp Ss Dp Ds;
eq1 = -Ss + alpha + 0.17*Ps - 1*Pc;
eq2 = -Sp + beta + 0.2*Pp;
eq3 = -Ds + gamma - 0.2*Ps + 1*Pp;
eq4 = -Dp + lambda - 0.17*Pp + 1*Ps;
eq5 = Ss - Ds;
eq6 = Sp - Dp;
ans1 = solve(eq1,eq2,eq3,eq4,eq5,eq6,'Ps','Pp','Ss','Ds','Sp','Dp');
disp('Ps')
vpa(ans1.Ps,3)
disp('Pp')
vpa(ans1.Pp,3)
disp('Ss')
vpa(ans1.Ss,3)
disp('Ds')
vpa(ans1.Ds,3)
disp('Sp')
vpa(ans1.Sp,3)
disp('Dp')
vpa(ans1.Dp,3)
I will be varying several of the variables (on Ps, Pp, and Pc), and recording the coefficient on Pc in each of the reduced form equations (i.e. the coefficient on Pc that shows up after vpa(ans1.xx)--so in the case above, it would be a 1x6 vector [-0.429,-1.16,-1.07,-1.07,-0.232,-0.429,-1.16]).
I'm very new to MATLAB, but I'm sure I can figure out how to implement the loop code to do the model iterations. What I can't figure out is how to record the vector of coefficients after each iteration. Is there some "accessor" that will give me just the one coefficient for each equation each time?
Something like vpa(ans1.ps.coef(pc)) (which is a total shot in the dark, and it's wrong, but hopefully you get the idea).
There's probably a better way to do this, but this is all I could come up to at this moment.
Step 1:
In order to obtain the coefficient of Pc as a double from ans1.Ps, you can use the subs function, as follows:
subs(ans1.Ps,{alpha,Pc,beta,gamma,lambda},{0,1,0,0,0});
Step 2a:
To get a vector of all coefficients per ans1 expression (say ans1.Ps) you can use something like this:
N=numel(symvar(ans1.Ps)); % obtain number of coefs
cp=num2cell(eye(N)); % create a cell array using unit matrix, so each iteration a different coef will be selected
for n=1:N;
coefs(n)=subs(ans1.Ps,{alpha,Pc,beta,gamma,lambda},cp(n,:));
end
Step 2b:
Alternatively, you want to get just Pc, but from all the ans1 expressions. If so then you can do the following:
SNames = fieldnames(ans1); % get names of ans1 expressions
for n = 1:numel(SNames)
expr = ans1.(SNames{n}); % get the expression itself
pc(n)=subs(expr,{alpha,Pc,beta,gamma,lambda},{0,1,0,0,0}); % obtain just pc
end
You can now combine the two if you want all info about the coefficients.
Edit:
To store the retrieved Pc per iteration you can do the following:
alpha=[3 1 4 6 7] % just a vector of values
beta = [6 7 8 5 2]
SNames = fieldnames(ans1); % get names of ans1 expressions
for n = 1:numel(SNames)
expr = ans1.(SNames{n}); % get the expression itself
for n1=1:numel(alpha)
for n2=1:numel(beta)
pc(n,n1,n2)=subs(expr,{alpha,Pc,beta,gamma,lambda},{alpha(n1),1,beta(n2),0,0})
end
end
end