找回密码
 注册
Simdroid-非首页
查看: 303|回复: 31

一个递归或迭代求解问题,超大运算量,如何实现?

[复制链接]
发表于 2009-12-26 08:43:36 | 显示全部楼层 |阅读模式 来自 山东淄博
本帖最后由 wanglu 于 2009-12-28 19:52 编辑

原帖位置:http://www.ilovematlab.cn/thread-60022-1-1.html
问题描述:


我用Forcal给出了递归解法,但当m=4时,运算时间就很长了,这倒不是Forcal速度太慢的缘故,此例若转换成C/C++代码,Forcal的速度估计在C/C++速度的1/10左右,甚至更快一些。速度慢的原因主要在于存在大量的函数调用。

如果能保存V(t,m)的计算结果,以后不再计算,估计能大幅提高速度。但难点在于,此问题中存在一个积分(我用的积分方法是徐士良算法中的连分式积分法),不知道积分运算时V(t,m)中的t为多少,故难以保存中间结果。

Matlab、mmtc、Maple等高手们看一下有什么好方法,最好给出代码,实际运行一下。

据原贴主xl0418讲,有人算过m=50,以运行10分钟为限,大家看能算到多少?

下面是Forcal代码及结果:


  1. SetTalk[false];
  2. !SetRealStackMax(1000);
  3. Rm(t,m:j,s,a,b,h:hVm,iRm)=
  4. {
  5.   iRm++, h=0.00001,
  6.   sys::call(2,hVm :t+h,m : &a),  //计算s=Vm(t+h,m)
  7.   sys::call(2,hVm :t,m : &b),    //计算s=Vm(t,m)
  8.   s=[a-b]/h,
  9.   j=0,(j<=m).while{
  10.     sys::call(2,hVm :t,j : &a), sys::call(2,hVm :t,m-j : &b),  //计算a=Vm(t,j),   b=Vm(t,m-j)
  11.     s=s+a*b,
  12.     j++
  13.   },
  14.   s-[1-which(m<1,0,1)] //最后返回这个值。看这句有没有问题:取m<1,而不是m<=1
  15. };
  16. //Fkappa将返回s的值。mm是模块变量,因调用Rm(t,mm-1)时mm将改变,故用a预先保存,函数返回前恢复mm的值
  17. Fkappa(t:a,s,kappa:mm,iFkappa)= iFkappa++, kappa=0, a=mm, s=t^(2*kappa)*Rm(t,mm-1), mm=a, s;
  18. Vm(t,m:h,kappa:mm,hFkappa,iVm)=
  19. {
  20.   iVm++, h=-1, kappa=0,
  21.   if[m<=0,return(t)], if[m==1,return(1/3*h*t^3)],
  22.   which(m<=1,0,1)*Vm(t,m-1)+h*{mm=m, XSLSF::fpqg[hFkappa,0,t,1e-6]}  //XSLSF::fpqg即徐士良算法中的连分式积分法
  23. };
  24. pert(t)=t-1/3*t^3+2/15*t^5-17/315*t^7;
  25. main(t,m:k,s:hFkappa,hVm,iRm,iFkappa,iVm)=
  26. {
  27.   iRm=0, iFkappa=0, iVm=0,
  28.   hFkappa=HFor("Fkappa"), hVm=HFor("Vm"),  //预先获得函数Fkappa和Vm的句柄,函数调用时将用到
  29.   s=0,k=0,(k<=m).while{
  30.     s=s+Vm(t,k),
  31.     k++
  32.   },
  33.   printff{"\r\n结果={1,r,-25.16}, 验证pert(t)={2,r,-25.16}, 函数Rm调用次数{3,i,-8}, 函数Fkappa调用次数{4,i,-8}, 函数Vm调用次数{5,i,-8}",s,pert(t),iRm,iFkappa,iVm},
  34.   s  //返回s
  35. };
  36. main[1,1];
  37. main[1,2];
  38. main[1,3];
  39. main[3,1];
  40. main[3,2];
  41. main[3,3];
复制代码
结果:

结果=0.6666666666666667      , 验证pert(t)=0.7460317460317461      , 函数Rm调用次数0      , 函数Fkappa调用次数0      , 函数Vm调用次数2      
结果=0.8000050003347501      , 验证pert(t)=0.7460317460317461      , 函数Rm调用次数65      , 函数Fkappa调用次数65      , 函数Vm调用次数394   
结果=0.7460312361721437      , 验证pert(t)=0.7460317460317461      , 函数Rm调用次数33702  , 函数Fkappa调用次数33702  , 函数Vm调用次数203761  
结果=-6.                      , 验证pert(t)=-91.62857142857143      , 函数Rm调用次数0      , 函数Fkappa调用次数0      , 函数Vm调用次数2      
结果=26.40004500009          , 验证pert(t)=-91.62857142857143      , 函数Rm调用次数129    , 函数Fkappa调用次数129    , 函数Vm调用次数778   
结果=-91.62900091017789      , 验证pert(t)=-91.62857142857143      , 函数Rm调用次数163158  , 函数Fkappa调用次数163158  , 函数Vm调用次数982033

我还有一个问题,放在maple板块:一个含积分的等式优化题
位置:http://forum.simwe.com/thread-910945-1-1.html
大家帮忙解决一下?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
发表于 2009-12-26 20:25:45 | 显示全部楼层 来自 浙江杭州
Simdroid开发平台
看了一下,问题描述的不是很清楚,当k=0是时,v(t,k)为v(t,0),也就是要求第一、二两个式子Rm(t,-1)和V(t,0)的值,这两个值也没办法求呀。

另外,原贴Rm似乎还有导数项。

不过,这种问题虽然繁琐,但一点一点解应该还是没有问题的吧。
回复 不支持

使用道具 举报

 楼主| 发表于 2009-12-26 22:24:16 | 显示全部楼层 来自 山东淄博
看了一下,问题描述的不是很清楚,当k=0是时,v(t,k)为v(t,0),也就是要求第一、二两个式子Rm(t,-1)和V(t,0)的值,这两个值也没办法求呀。

另外,原贴Rm似乎还有导数项。

不过,这种问题虽然繁琐,但一点一点解 ...
messenger 发表于 2009-12-26 20:25

一时疏忽,问题图片贴错了,已经修改了。另外,V(t,m)对t求一阶导数。
matlab求导比较方便,Forcal中还没有求导函数,我用[f(x+h)-f(x)]/h代替了。
回复 不支持

使用道具 举报

发表于 2009-12-27 13:51:26 | 显示全部楼层 来自 广东湛江
这个我也在写啊,哈哈,但是很难啊
回复 不支持

使用道具 举报

发表于 2009-12-27 14:55:10 | 显示全部楼层 来自 浙江杭州
大致算了一下,这个题目如果迭代算在技术上没什么难度,只是比较麻烦,只要仔细一点就行了。

Matlab的下标不能从零开始,所以比较麻烦,因为下标不能为零,所以下标要都加1,有的还要减1。

下面是代码,除了下标可能不对(懒得检查了,反正又不是我的问题),其他的技术问题都是对的。

算了一下t=10,m=10的情况,只是几秒钟。


  1. syms t h;
  2. v=sym(zeros(1,11));
  3. rm=sym(zeros(1,11));
  4. h=1;
  5. v(1)=t;
  6. v(2)=1/3*h*t^3;
  7. m=10;
  8. for k1=2:m;
  9. k=k1+1;
  10. rm1=diff(v(k-1),t);
  11. rm2=sym(0);

  12. for j=1:k1
  13. temp=v(j)*v(k-j)-(1-k1+1);
  14. rm2=rm2+temp;
  15. end

  16. rm(k-1)=rm1+rm2;

  17. v(k)=v(k-1)+h*int(rm(k-1),t);
  18. end

  19. main=sum(v);
  20. t=10;
  21. subs(main,t)
复制代码
回复 不支持

使用道具 举报

发表于 2009-12-27 17:35:14 | 显示全部楼层 来自 广东湛江
thanks 哈哈!
回复 不支持

使用道具 举报

 楼主| 发表于 2009-12-27 17:44:11 | 显示全部楼层 来自 山东淄博
看了messenger 版主的代码,虽然不懂matlab的代码,但有些明白了。这个问题用数值解法没有优势,完全可以由解析法解决,而且有很高的效率。

我手算试了一下,用递推公式可以得到v(t,m)和Rm(t,m)的公式,微分式和积分式也可得到。但手算工作量太大,也容易出错。这正好发挥matlab(或mmtc、maple)的优势,先获得解析解,然后计算,就比较简单了。

不知我的理解对不对?

我将这段代码发给原贴主看一下。替他先谢谢messenger 版主了。

另外,另一个问题,放在maple板块:一个含积分的等式优化题
位置:http://forum.simwe.com/thread-910945-1-1.html
是否有解析解呢?
回复 不支持

使用道具 举报

 楼主| 发表于 2009-12-27 18:14:18 | 显示全部楼层 来自 山东淄博
不过,关于这个问题我有个预感,是不是当m大到一定数时matlab就算不出了?
这个似乎不是时间问题。
因为随m的增大,符号解的表达式将很长,matlab似乎不能编译太长的表达式?
大家验证一下?
回复 不支持

使用道具 举报

发表于 2009-12-27 19:25:24 | 显示全部楼层 来自 浙江杭州
嗯,是的,这个问题有些碰巧的成份。因为迭代公式都是多项式,积分、求导都比较方便,所以正好可以发挥解析解法的优势。

不过,觉得这个问题如果用数值解法,用数值方法求积分、求导,应该也可以,不过要比解析解法麻烦一些。最重要的是解析解法对自变量 t 没有要求,而数值解法要给出具体的 t ,这也会增加数值积分和求导的难度。


看了messenger 版主的代码,虽然不懂matlab的代码,但有些明白了。这个问题用数值解法没有优势,完全可以由解析法解决,而且有很高的效率。

我手算试了一下,用递推公式可以得到v(t,m)和Rm(t,m)的公式,微分式和积分式也可得到。但手算工作量太大,也容易出错。这正好发挥matlab(或mmtc、maple)的优势,先获得解析解,然后计算,就比较简单了。

不知我的理解对不对?
wanglu 发表于 2009-12-27 17:44
回复 不支持

使用道具 举报

发表于 2009-12-27 19:29:01 | 显示全部楼层 来自 浙江杭州
如果表达式太长的话,可能运算时间较长。不过,表达式的长度限制倒不是问题,因为此问题是加法运算,可以设中间变量,将一个较长的表达式拆分。比如一个100项相加的表达式,代换成2个变量相加,每一个变量为50项相加。

不过,关于这个问题我有个预感,是不是当m大到一定数时matlab就算不出了?
这个似乎不是时间问题。
因为随m的增大,符号解的表达式将很长,matlab似乎不能编译太长的表达式?
大家验证一下?
wanglu 发表于 2009-12-27 18:14
回复 不支持

使用道具 举报

 楼主| 发表于 2009-12-27 20:01:13 | 显示全部楼层 来自 山东淄博
如果表达式太长的话,可能运算时间较长。不过,表达式的长度限制倒不是问题,因为此问题是加法运算,可以设中间变量,将一个较长的表达式拆分。比如一个100项相加的表达式,代换成2个变量相加,每一个变量为50项相加 ...
messenger 发表于 2009-12-27 19:29

明白了。

另外,积分式中那个指数2k中的k取0是一个特殊情况,原贴主为了简化计算,将k取0了。若k不为0,而是3.2或者是其他数值,解析解法还能求解吗?
回复 不支持

使用道具 举报

发表于 2009-12-27 20:50:23 | 显示全部楼层 来自 浙江杭州
k不为零应该也没问题,原来被积函数Rm为多项式,再乘一个tau^k,还是多项式,这对积分来说没有什么新困难。

另外,积分式中那个指数2k中的k取0是一个特殊情况,原贴主为了简化计算,将k取0了。若k不为0,而是3.2或者是其他数值,解析解法还能求解吗?
wanglu 发表于 2009-12-27 20:01
回复 不支持

使用道具 举报

发表于 2009-12-27 20:52:50 | 显示全部楼层 来自 广东湛江
这个一个递归或迭代求解问题目的用来干什么的呢??
回复 不支持

使用道具 举报

发表于 2009-12-27 21:01:22 | 显示全部楼层 来自 广东湛江
h=1;
v(1)=t;
v(2)=1/3*h*t^3;
其中的作用是干什么用的呢??
回复 不支持

使用道具 举报

发表于 2009-12-27 21:09:18 | 显示全部楼层 来自 浙江杭州
v(1)、v(2)是初值呀,递归或递推都要有初值呀。比如x(i+2)=x(i+1)+x(i),要知道x(1)和x(2)的值才能知道x(3)的值,进而推得其他x的值。

h=1;
v(1)=t;
v(2)=1/3*h*t^3;
其中的作用是干什么用的呢??
linhengcan126 发表于 2009-12-27 21:01
回复 不支持

使用道具 举报

 楼主| 发表于 2009-12-27 21:10:22 | 显示全部楼层 来自 山东淄博
k不为零应该也没问题,原来被积函数Rm为多项式,再乘一个tau^k,还是多项式,这对积分来说没有什么新困难。


messenger 发表于 2009-12-27 20:50

谢谢了!
看来解析解法和数值解法各有所长,需要用其所长啊。
回复 不支持

使用道具 举报

 楼主| 发表于 2009-12-27 21:11:19 | 显示全部楼层 来自 山东淄博
h=1;
v(1)=t;
v(2)=1/3*h*t^3;
其中的作用是干什么用的呢??
linhengcan126 发表于 2009-12-27 21:01

这个我也不清楚,请查看原帖。
原帖位置:http://www.ilovematlab.cn/thread-60022-1-1.html
回复 不支持

使用道具 举报

发表于 2009-12-27 21:22:15 | 显示全部楼层 来自 广东湛江
有时候我在怀疑,我们学习这么深,这些函数的真正意义是干什么的呢??
回复 不支持

使用道具 举报

发表于 2009-12-27 21:39:05 | 显示全部楼层 来自 浙江杭州
递推和递归在实际问题中还是很常见的

有时候我在怀疑,我们学习这么深,这些函数的真正意义是干什么的呢??
linhengcan126 发表于 2009-12-27 21:22
回复 不支持

使用道具 举报

发表于 2009-12-27 21:42:23 | 显示全部楼层 来自 广东湛江
能不能举个例子,我感觉不到啊,thanks!
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-4-29 02:18 , Processed in 0.061732 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表