【发布时间】:2014-10-30 20:13:05
【问题描述】:
我正在构建一个代码来解决差异。等式:
function dy = KIN1PARM(t,y,k)
%
% version : first order reaction
% A --> B
% dA/dt = -k*A
% integrated form A = A0*exp(-k*t)
%
dy = -k.*y;
end
我希望对这个方程进行数值求解,并将结果(y 作为 t 和 k 的函数)用于最小化实验值以获得参数 k 的最佳值。
function SSE = SSE_minimization_1parm(tspan_inp,val_exp,k_inp,y0_inp)
f = @(Tt,Ty) KIN1PARM(Tt,Ty,k_inp); %function to call ode45
size_limit = length(y0_inp);
options = odeset('NonNegative',1:size_limit,'RelTol',1e-4,'AbsTol', 1e-4);
[ts,val_theo] = ode45(f, tspan_inp, y0_inp,options); %Cexp is the state variable predicted by the model
err = val_exp - val_theo;
SSE = sum(err.^2); %sum squared-error
绘制实验和计算数据的主要代码是:
% Analyzing first order kinetics
clear all; clc;
figure_title = 'Experimental Data';
label_abscissa = 'Time [s]';
label_ordinatus = 'Concentration [mol/L]';
%
abscissa = [ 0;
240;
480;
720;
960;
1140;
1380;
1620;
1800;
2040;
2220;
2460;
2700;
2940];
ordinatus = [ 0;
19.6;
36.7;
49.0;
57.1;
64.5;
71.4;
75.2;
78.7;
81.3;
83.3;
85.5;
87.0;
87.7];
%
title_string = [' Time [s]', ' | ', ' Complex [mol/L] ', ' '];
disp(title_string);
for i=1:length(abscissa)
report_raw_data{i} = sprintf('%1.3E\t',abscissa(i),ordinatus(i));
disp([report_raw_data{i}]);
end;
%---------------------/plotting dot data/-------------------------------------
%
f = figure('Position', [100 100 700 500]);
title(figure_title,'FontName','arial','FontWeight','bold', 'FontSize', 12);
xlabel(label_abscissa, 'FontSize', 12);
ylabel(label_ordinatus, 'FontSize', 12);
%
grid on; hold on;
%
marker_style = { 's'};
%
plot(abscissa,ordinatus, marker_style{1},...
'MarkerFaceColor', 'black',...
'MarkerEdgeColor', 'black',...
'MarkerSize',4);
%---------------------/Analyzing/----------------------------------------
%
options = optimset('Display','iter','TolFun',1e-4,'TolX',1e-4);
%
CPUtime0 = cputime;
Time_M = abscissa;
Concentration_M = ordinatus;
tspan = Time_M;
y0 = 0;
k0 = rand(1);
[k, fval, exitflag, output] = fminsearch(@(k) SSE_minimization_1parm(tspan,Concentration_M,k,y0),k0,options);
CPUtimex = cputime;
CPUtime_delay = CPUtimex - CPUtime0;
%
%---------------------/plotting calculated data/-------------------------------------
%
xupperlimit = Time_M(length(Time_M));
xval = ([0:1:xupperlimit])';
%
yvector = data4plot_1parm(xval,k,y0);
plot(xval,yvector, 'r');
hold on;
%---------------------/printing calculated data/-------------------------------------
%
disp('RESULTS:');
disp(['CPU time: ',sprintf('%0.5f\t',CPUtime_delay),' sec']);
disp(['k: ',sprintf('%1.3E\t',k')]);
disp(['fval: ',sprintf('%1.3E\t',fval)]);
disp(['exitflag: ',sprintf('%1.3E\t',exitflag)]);
disp(output);
disp(['Output: ',output.message]);
对应的函数,它使用优化的参数k来产生计算出的y = f(t)数据:
function val = data4plot_1parm(tspan_inp,k_inp,y0_inp)
f = @(Tt,Ty) KIN1PARM(Tt,Ty,k_inp);
size_limit = length(y0_inp);
options = odeset('NonNegative',1:size_limit,'RelTol',1e-4,'AbsTol',1e-4);
[ts,val_theo] = ode45(f, tspan_inp, y0_inp, options);
代码运行优化周期时总是给出不同的参数 k 值,这与使用 ln(y) vs t 计算的值不同(对于该系列的 exp.数据,应该在 7.0e-4 左右)。
查看 ode 求解器 (SSE_minimization_1parm => val_theo) 的结果,我发现 ode 函数给了我一个零向量。
有人可以帮我弄清楚 ode 求解器的情况吗?
非常感谢!
【问题讨论】:
-
我的三个cmets:1)当您明确指出可以解析求解时,为什么要以数值求解该积分(参考
integrated form A = A0*exp(-k*t)),您可以尝试将数据拟合到这条曲线然后使用nlinfit()。 2)y0 = 0如果您以初始条件 y0 = 0 开始指数增长/衰减,您期望解决方案是什么? 3)plot(abscissa, ordinatus, 'kx')看起来并不完全适合指数增长,也许plot(ordinatus, abscicca, 'kx')可以。 -
谢谢! 1)这是一个概念证明。我有更复杂的 diff 版本。系统,不存在解析解。我想确保这段代码有效。 2) 我明白了。问题:是否有可能在代码中包含 y0 的最小化,不知何故..? 3) 是的。实际上,我犯了一个错误并遗漏了重要信息。 plot(abscissa,100-ordinatus,'kx') 应该服从集成版本 y = y0*exp(-k*x) 对于当前数据集,从半对数图计算的 k 值为 7.11e -4。而且我没有得到它......
-
您可以将参数向量交给
fminsearch进行优化。类似于:par0 = [k0, y0],然后是fminsearch(@minimize, par0),最后在函数minimize中的前两行将是y0 = par[1]; k = par[2]。然后优化器还将包括y0。在我的代码中修复ordinatus, abscissa-thingy 应该不是问题。祝你好运! -
谢谢!这以某种方式起作用, y0 = par(1); k = 标准杆(2);但是,现在计算需要时间,并且 k 值非常不同 k_opt = 4.1872e+07 ...更多,代码给出了两个 y0 值,分别为 -0.0950 和 104.4489 ...绘图的数据。奇怪
标签: matlab