转帖:求解非线性方程
mathcad吧
全部回复
仅看楼主
level 11
vv_0147 楼主
转帖:求解非线性方程
来源:小木虫(http://emuch.net/);
使用相关的软件:1stOpt;
内容:
题目看下图,应该用什么方法求解这种问题
网友的解答:
多解吧,1stOpt求解:
CODE:Parameter r=[-10000,0];
Function 2*a*b-2*a*b*cos(a)*cosh(b)+(b^2-a^2)*sin(a)*sinh(b)=0;
a^2=-r*(1+sqrt(1-4/r));
b^2=r*(1-sqrt(1-1/r));
No. r
1 -314.350542117175
2 -591.945294828352
3 -314.350542117124
4 -77.490066467595
5 -18.31
18538130735

6 -314.350542117147
7 -394.552971487191
8 -77.4900664675666
9 -591.945294828371
10 -39.2416278340712
11 -77.4900664675258
12 -1420.99234187037
13 -39.2416278340656
14 -40.7437817193568
15 -0.000110023439544683
16 -0.000190975109419403
17 -0.000219338722890091
18 -0.000225096567150581
2015年10月22日 07点10分 1
level 12
这个MC做不了。
2015年10月22日 08点10分 2
level 12
我验算了一下,没想到这么高端的1stOpt找到的这几个根都不是
正确的
……
解出a,b准备代入。因为a和b各有两个值,如果要求出全部的λ,需要将a和b的组合分别建立成为独立的方程来解,然后把结果综合到一起,去掉重复值。
从下图可以看出,A(x)和D(x)貌似是等价的,B(x)和C(x)貌似是等价的。
把楼主的数据复制黏贴过来,转换为数学格式。
然后验算,可以看出1stOpt给出的解中后面5个是“假的”,其他的解看上去还比较好。
2015年10月22日 12点10分 3
level 12
我用符号计算粗算出了一个解:
很明显这个解要比1stOpt给出的所有解都好一些。
嗯,而且因为A,B,C,D是连续的,那么用MC的数值计算就可以得到全部的解,而且还可以进一步做到解的优化。尽管用MC解这种非线性函数的要麻烦一些,但现在看,我有信心的认为MC给出来的解一定会比高大上的1stOpt来得更好。
2015年10月22日 12点10分 4
level 12
嗯,下面两幅图看,当A,B,C,D都取绝对值的时候,这四个函数是等价的,那就把问题简化了。
2015年10月22日 12点10分 5
level 12
下面我详细讲解一下主程序,里面涉及到很多这个函数的特征,以及MC的求解命令块的运行特点。我想对这个主程序进行详细的解析,对大家更深刻的理解MC是有帮助的。
主程序全貌见6楼,我这里只是分部分来说:
第一部分
初步求解得到所有可能的解集。我让估值的步长为1,然后在每个估值上进行一次求解命令块的计算得到一个解,然后对这个解求集合。
从A(x)的放大图看,最密集处的解之间的距离也有约20个单位长度,实际上步长可以选择用20的,这样可以节约很多求解时间,也可以是最后得到的集合更舒朗有效。
但是我怕因为我选择了比较长的步长而遗漏可能存在的解,所以还是保守的使用了步长为1。
从A(x)的全值域图形可以看出,当x>0时,A(x)为复数。
@vv_0147 的转载看,原作者是不希望A(x)得到复数值的,所以在1stOpt中给出的计算值域是[-10000,0],所以我筛选根的时候,也使用了这个值域。这在之后的程序里也能够看出来。
尽管我知道A(x)是连续的,在TOL范围内应该不会发生解发散的情况,但是为了以防万一,我还是使用了on error。使用MC的求解命令块进行编程的时候,这点是需要注意的,否则真的会让自己陷入麻烦。
尽管我给出的估值范围是-10000到0,但不能确保MC不会得到小于-10000的解,为了防止发生这种浪费资源的错误,我用了一个if分支把可能出现的小于-10000的解过滤掉。
第二部分
第一部分中所得到的ra有100多个,里面有很多非常相近的值,不相等,所以用集合函数也没办法去掉。
我对第一部分所得到的ra进行了一些分析,对照A(x)的图形,确定将ra的值放大100倍之后取整,再缩小100倍,这样就能够想办法去除掉所有相近的值了。实际上,从A(x)的图形中可以看出,所有根之间的距离都是大于1的,所以这一步还可以直接trunc(ra),而不必像我这样非要用一个很小的窗口来过滤重复值。
对取整之后得到的ra再次求集合,就完成了对相近值的过滤了,得到了rb。
rb中的元素并不是精确解,它们标示出了精确解所处的大概坐标位置,要得到精确解,就需要用rb来筛ra中的大量的近似值。
我对rb中所有元素进行遍历,因为我上面使用的窗口是0.01,所以在这里我仍然用rb±0.01作为筛选ra的窗口。用trim(match())组合去掉其他无关的解,每次仅让MC从ra中筛出一组近似解,赋值给rc。
rc可能有很多个,它们之间距离很近,但只会有一个或者两个解,代入AA(x)之后使它的值最小,也就是所有近似解里的最优解,通过lookup找到这个最有解,这基本上就是我要求的值了。
有一个最优解是可以理解的,那么为什么还会有两个最优解的情况呢?看下图:
因为我是用的A(x)的绝对值来求解的,在AA(x)等于0的附近,可能会有两个x同时满足这个条件。假设解的真值是X,就有可能发生:
|AA(x1)-AA(X)| = |AA(x2)-AA(X)|
的情况。既然这两个解分别处于真值X的左右,那么我对这两个解求平均值的话,应该会得到一个更好的解,所以使用了mean函数。
lookup和match一样,返回的是一个向量而不是标量,所以即使只有一个解,我也要从lookup向量里把它提取出来。
最后一行,我在第一部分里已经说了,x大于0的时候A(x)为复数,所以要去掉大于0的解。嗯,用我这个解法是能够得到1个大于0的解的,约等于10^-11。
2015年10月22日 15点10分 7
数学果然是思维的体操啊,mc就是体操的节奏啊。
2015年10月23日 00点10分
level 12
源文件我就不上传了,终归这种函数是一个特例,我也是按照这个特例量体裁衣编的程序,换成另外一个函数就不好用了。
我是想说,用MC进行数值编程计算的时候,尤其是在求解的时候,一定要首先对需要求解的函数进行绘图,从而能够直观的了解自己在做什么,从而采取相应的对策。闭着眼睛一味的编程,只能是自造麻烦。
2015年10月22日 15点10分 8
level 12
嗯,百密一疏,在这一步里我应该用f(rc),而不是AA(rc),下图我已经改过来了:
2015年10月22日 15点10分 9
level 11
vv_0147 楼主
我只是看到不用初始值就可以求解,比较有趣,所以转发进来的。
希望老朱有机会给讲讲1stopt的应用。最近忙完,计划买本书。
2015年10月23日 03点10分 10
level 12
另外一种解法使用了https://tieba.baidu.com/p/3229679092中的定值域求极值的方法,然后root求极值之间的根,更舒朗,更明白,运行更快一些,基本上是秒解了。
并且用符号的就地运算真的非常快。不知道MC12使用了Mupad引擎之后到底发生了什么,如果用“→”都慢的要死,如果用“符号”菜单里的命令的话就跟以前的MC用Maple引擎时候的效果是一样的快了。
求极值的那套算法,我直接搬过来的:
然后在给定区间内root就OK了。
整个过程用了0.4秒,跟1stOpt一样快了。
2015年10月23日 06点10分 11
level 12
小木虫里的那个1stOpt程序也有问题,我不知道他用的是哪个版本,使用他给出的CODE根本不会发生有效的求解计算。
我用的1stOpt 6.0,编码如下:
ComplexStr = i;
Parameter r=[-10000,0];
ConstStr a=sqrt(r)*sqrt(sqrt(1-(4/r))+1)*i,b=sqrt(r)*sqrt(sqrt(1-(1/r))-1)*i;
Function 2*a*b-2*a*b*cos(a)*cosh(b)+(b^2-a^2)*sin(a)*sinh(b)=0;
但根本不能同时求出很多解,得到的解的效果也很差:
====== 结果 ======
迭代数: 16
计算用时(时:分:秒:微秒): 00:00:00:349
计算结束原因: 达到收敛判断标准
优化算法: 通用全局优化算法(UGO1)
目标函数值(最小): 10000000000
r: -8324.77164920419
====== 计算结束 ======
嗯,1stOPt我也没用的很明白,怎么同时得到所有满足条件的解,我查了半天手册也没找到相应的语句。不过,至少我上面这么写,1stOpt可以正确计算,小木虫里的那个家伙给出的代码很扯淡的。
2015年10月23日 07点10分 12
1