我使用MATLAB使用integral3执行三重积分,它运行速度非常慢。我想知道是否有办法加速它。我猜它是因为我把abstol设置错了。不知道如何处理它。 PS下面的代码工作没有语法错误。有几件事我不知道如何选择,弃用,方法等。
clear all
syms gamma1
syms gamma2
syms z
syms v
Nt=16; sigmanoise=10^(-7.9); c3=0.129; c1=(1-c3)/2;a2=0;b2=0;
a1=0.0030; b1= 0.0030; A1= 1.5625e-04,A2=0; B1= 7.8125e-05;B2=0;
theta= 3.1623;lambda1= 4.9736e-05;lambda2=0;p1=1;p2=0; alpha1=2; alpha2=4;delta1=2/alpha1; delta2=2/alpha2;beta1=0.025; beta2=0.025;
a= gamma1^-1+gamma2^-1+2*gamma1^(-0.5)*gamma2^(-0.5);
laplacesgi=(exp(+2*pi*j.*z*a)-1)./(2*pi*j*z);
laplacesgi=matlabFunction(laplacesgi);
laplacenoi=exp(-2*pi*j.*z*theta*sigmanoise/Nt);
laplacenoi=matlabFunction(laplacenoi);
interfere= @(gamma1,gamma2,v,z)( (1 -2*c1-c3./(1+2*pi*j*z*theta*v.^(-1))).*(A1.*(v).^(delta1-1).*exp(-a1.*(v).^ (delta1./2))+B1.*(v).^(delta2-1) .*(1-exp(-b1.*(v).^ (delta2./2)))));
gscalar =@(gamma1,gamma2,z)integral(@(v)(interfere(gamma1,gamma2,v,z)),gamma2,inf);
g = @(gamma1,gamma2,z)arrayfun(gscalar,gamma1,gamma2,z);
lp= A1*(gamma1)^(delta1-1)*exp(-a1*(gamma1)^ (delta1/2))+B1*(gamma1)^(delta2-1)*(1-exp(-b1*(gamma1)^ (delta2/2)))+A2*gamma1^(delta1-1)*exp(-a2*gamma1^(delta1/2))+ B2*gamma1^(delta2-1)*(1-exp(-b2*gamma1^ (delta2/2)));%;
dk1=((2*pi*lambda1))/(beta1^2)*(1-exp(-a1*(gamma2)^(delta1/2))*(1+(gamma2)^(delta1/2)*a1))+ pi*lambda1*gamma2^(delta2)*p1^delta2-((2*pi*lambda1)/(beta1^2))*(1-exp(-b1*(gamma2)^(delta2/2))*(1+(gamma2)^(delta2/2)*b1));
dk2=((2*pi*lambda2))/(beta2^2)*(1-exp(-a2*(gamma2)^(delta1/2))*(1+(gamma2)^(delta1/2)*a2))+ pi*lambda2*gamma2^(delta2)*p2^delta2-((2*pi*lambda2)/(beta2^2))*(1-exp(-b2*(gamma2)^(delta2/2))*(1+(gamma2)^(delta2/2)*b2));
dk=dk1+dk2;
lcp= A1*(gamma2)^(delta1-1)*exp(-a1*(gamma2)^ (delta1/2))+B1*(gamma2)^(delta2-1)*(1-exp(-b1*(gamma2)^ (delta2/2)))+A2*gamma2^(delta1-1)*exp(-a2*gamma2^ (delta1/2))+ B2*gamma2^(delta2-1)*(1-exp(-b2*gamma2^(delta2/2)));%;
pdflast=lp*lcp*exp(-dk);
pdflast=matlabFunction(pdflast);
pdflast= @(gamma1,gamma2)arrayfun(pdflast,gamma1,gamma2);
gamma2min=@(gamma1)gamma1;
warning('off','MATLAB:integral:MinStepSize');
T = integral3(@(gamma1,gamma2,z)(laplacenoi(z).*laplacesgi(gamma1,gamma2,z).*pdflast(gamma1,gamma2).*exp(-g(gamma1,gamma2,z))),0,inf,@(gamma2)gamma2,inf,0.05,1000,'abstol',1e-3)
我感谢任何想法或建议。
答案 0 :(得分:0)
对于评论来说这已经太长了,虽然它也没有给出答案,但我认为它可能会有所帮助,所以我会略微滥用答案表格。
我认为你的代码不能满足代码的基本目的:与人类沟通,可能是你自己的未来。
我不知道变量名称是否足够明确,在六个月内,他们仍然会告诉你到底是什么。如果他们是伟大的。如果没有,您可能希望改进它们。 (是的,命名内容是编程中最难的部分之一,但这并不会使它变得不那么重要。)
同样适用于评论:如果您不需要对公式发表评论,请为您提供更多权力。我不知道你在计算什么,所以我不理解你的公式并不是很重要。但是再一次,在几个月内想想自己,找一个问题:你是否希望发表评论,以便你知道这个因素是真的是正确的还是由一个人解决?
这里有一些我知道的事情:你的公式太宽大,无法立即被理解。简单的重新格式化有助于更好地查看结构。这是我如何重新格式化你的代码以开始从它做出正面或反面:
clear all
syms gamma1
syms gamma2
syms z
syms v
Nt=16;
sigmanoise=10^(-7.9);
c3=0.129;
c1=(1-c3)/2;
a2=0;
b2=0;
a1=0.0030;
b1=0.0030;
A1=1.5625e-04;
A2=0;
B1=7.8125e-05;
B2=0;
theta=3.1623;
lambda1=4.9736e-05;
lambda2=0;
p1=1;
p2=0;
alpha1=2;
alpha2=4;
delta1=2/alpha1;
delta2=2/alpha2;
beta1=0.025;
beta2=0.025;
a=gamma1^(-1)+gamma2^(-1)+2*gamma1^(-0.5)*gamma2^(-0.5);
laplacesgi=matlabFunction((exp(2*pi*1j*z*a)-1)./(2*pi*1j*z));
laplacenoi=matlabFunction(exp(-2*pi*1j*z*theta*sigmanoise/Nt));
interfere= @(gamma1,gamma2,v,z)( ...
(1 -2*c1-c3./(1+2*pi*j*z*theta*v.^(-1))).*(A1.*v.^(delta1-1).* ...
exp(-a1.*v.^(delta1./2))+B1.*v.^(delta2-1).*(1-exp(-b1.*v.^(delta2./2)))));
gscalar=@(gamma1,gamma2,z)integral(@(v)(interfere(gamma1,gamma2,v,z)),gamma2,inf);
g=@(gamma1,gamma2,z)arrayfun(gscalar,gamma1,gamma2,z);
lp=A1*gamma1^(delta1-1)*exp(-a1*gamma1^(delta1/2))+ ...
B1*gamma1^(delta2-1)*(1-exp(-b1*gamma1^(delta2/2)))+ ...
A2*gamma1^(delta1-1)*exp(-a2*gamma1^(delta1/2))+ ...
B2*gamma1^(delta2-1)*(1-exp(-b2*gamma1^(delta2/2)));
dk1=((2*pi*lambda1))/(beta1^2)*(1-exp(-a1*gamma2^(delta1/2))*(1+gamma2^(delta1/2)*a1))+ ...
pi*lambda1*gamma2^(delta2)*p1^delta2- ...
((2*pi*lambda1)/(beta1^2))*(1-exp(-b1*gamma2^(delta2/2))*(1+gamma2^(delta2/2)*b1));
dk2=((2*pi*lambda2))/(beta2^2)*(1-exp(-a2*gamma2^(delta1/2))*(1+gamma2^(delta1/2)*a2))+ ...
pi*lambda2*gamma2^(delta2)*p2^delta2- ...
((2*pi*lambda2)/(beta2^2))*(1-exp(-b2*gamma2^(delta2/2))*(1+gamma2^(delta2/2)*b2));
dk=dk1+dk2;
lcp=A1*gamma2^(delta1-1)*exp(-a1*gamma2^(delta1/2))+ ...
B1*gamma2^(delta2-1)*(1-exp(-b1*gamma2^(delta2/2)))+ ...
A2*gamma2^(delta1-1)*exp(-a2*gamma2^(delta1/2))+ ...
B2*gamma2^(delta2-1)*(1-exp(-b2*gamma2^(delta2/2)));
pdflast=matlabFunction(lp*lcp*exp(-dk));
pdflast=@(gamma1,gamma2)arrayfun(pdflast,gamma1,gamma2);
gamma2min=@(gamma1)gamma1;
T = integral3(@(gamma1,gamma2,z)( ...
laplacenoi(z).*laplacesgi(gamma1,gamma2,z).*pdflast(gamma1,gamma2).*exp(-g(gamma1,gamma2,z))), ...
0,inf,...
@(gamma2)gamma2,inf,...
0.05,1000,...
'abstol',1e-3)
一些注意事项:
您的代码包含以下行:
pdflast=lp*lcp*exp(-dk);
pdflast=matlabFunction(pdflast);
我过去常常回收变量。随着时间的推移,我学到了很难,它有助于调试和可读性,特别是如果你的值有不同的类型,就像在这里一样。
此时我还有几点要清理。例如,pdflast
在数组上运行正常,应删除行pdflast= @(gamma1,gamma2)arrayfun(pdflast,gamma1,gamma2);
,gamma2
调用中integral3
的下限是{{1}的函数并且应该更改为gamma1
。
计算机/ MATLAB是否关心这些?也许有些东西在它的位置滑落,但基本上是:不。所有这些变化都适合你,如果你在SO帖子中发送你的代码,对我们来说,读者。
我认为您对@(gamma1)gamma1
的定义是错误的:
g
cubature(即g=@(gamma1,gamma2,z)arrayfun(gscalar,gamma1,gamma2,z);
)将尝试使用一个或多个参数的非标量值调用此函数。最有可能的是,这些并不都是相同的大小,即使它们是,它也会期望获得3D结果,而不是矢量。尝试以这种方式致电integral3
:
g
检查这样的中间构建块确实是一个好主意。您真正需要的是>> g(1:2,1,1)
Error using arrayfun
All of the input arguments must be of the same size and shape.
Previous inputs had size 2 in dimension 2. Input #3 has size 1
Error in @(gamma1,gamma2,z)arrayfun(gscalar,gamma1,gamma2,z)
超过arrayfun
,如下所示:
gamma2
gscalar=@(gamma1,gamma2,z) ...
integral(@(v)(interfere(gamma1,gamma2,v,z)),gamma2,inf, ...
'ArrayValued',true);
g = @(gamma1,gamma2,z)arrayfun(@(gamma2)gscalar(gamma1,gamma2,z),gamma2);
我不知道您是否尝试检查interfere
是否存在任何已知或可疑的值。 (我只是打字的公式检查对我来说似乎是个好主意。)我怀疑公式是否正确地捕捉了你的意图:
interfere
此公式的潜在问题(除了interfere=@(gamma1,gamma2,v,z)( ...
(1-2*c1-c3./(1+2*pi*1j*z*theta*v.^(-1))).*(A1.*v.^(delta1-1).* ...
exp(-a1.*v.^(delta1./2))+B1.*v.^(delta2-1).*(1-exp(-b1.*v.^(delta2./2)))));
与*
等的使用有些不一致)是值不依赖于.*
和{完全{1}}。
当然,这种情况可能会发生,但如果您实际上是这样的话,那么首先在公式中包含gamma1
的理由是什么?
如果它应该是这样,你可能仍然需要使结果具有合适的大小:现在,gamma2
只是忽略它的前两个输入,这可能会使积分器绊倒:gamma1
应该返回一个3元素的向量。
您可能已经注意到,您的问题尚未得到令人满意的答案。我认为它目前的形式也不会。为了让志愿者看到你的问题,你需要让你很容易理解你在做什么:
interfere
结果附近interfere(1:3,1,1,1)
之外,符号数学可能与您的实际问题无关。 arrayfun
。如果你可以在没有它的情况下提出问题,可能会引起更多关注。当然,在这个过程中,对于每次迭代,测试你的代码(在说出matlabFunction
之后或在一个新的MATLAB会话中!)来检查问题是否仍然存在。如果不是,您可能已经找到了隐藏基本问题的提示。
有关该主题的更长时间的讨论,请参阅https://meta.stackexchange.com/questions/18584/how-to-ask-a-smart-question以及与该讨论相关的指南。