使用根并在MATLAB中求解

时间:2017-05-01 15:02:41

标签: matlab

我有一个类似的等式:

enter image description here

这里a,b,c,d,e,f,g,h是常数。我想改变k从.6到10与0.1间隔,并找到w。在MATLAB中有两种方法可以做到这一点。

一种方法是将此等式转换为形式的等式(某物)w ^ 8-(其他)w ^ 6 ....-(另外的东西)w ^ 0 = 0,然后使用命令MATLAB中的“根”(方法1)。

另一种方法是定义符号函数然后执行程序。当您使用此方法时,您可能不需要进一步简化表达式,您可以将其放在第一个表单中(方法2)。

两种方式都显示在下面的脚本中:

%%% defining values
clear; clc;
a=0.1500;
b=0.20;
c=0.52;
d=0.5;
e=6;
f=30;
g=18;
h=2;

%% Method 1: varying k using roots
tic
i=0;
for k=.6:.1:10
    i=i+1;
    t8=a;
    t7=0;
    t6=-(1+e+a*(c+g))*(k^2) ;
    t5=0;
    t4=(k^2*(b+f+(c*e+g)*k^2)-a*(d+h-c*g*k^4));
    t3=0;
    t2=k^2*(d*(e+a*g)+h+a*c*h-(c*f+b*g)*k^2);
    t1=0;
    t0=(a*d*h)-(d*f+b*h)*k^2;
    q=[t8 t7 t6 t5 t4 t3 t2 t1 t0];
    r(i,:)=roots(q);
end
krho1(:,1)=.6:.1:10;
r_real=real(r);
r_img=imag(r);
dat1=[krho1 r_real(:,1) r_real(:,2) r_real(:,3) r_real(:,4) r_real(:,5) r_real(:,6) r_real(:,7) r_real(:,8)];
fnameout=('stack_using_roots.dat');
fid1=fopen(fnameout,'w+');
fprintf(fid1,'krho\t RR1\t RR2\t RR3\t RR4\t RR5\t RR6\t RR7\t RR8\t \r');
fprintf(fid1,'%6.4f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f \n',dat1');
fclose(fid1);
plot(krho1, r_real(:,1),krho1, r_real(:,2),krho1, r_real(:,3),krho1, r_real(:,4),krho1, r_real(:,5),krho1, r_real(:,6),krho1, r_real(:,7),krho1, r_real(:,8))
toc

%% Method 2: varying k using solve
tic
syms w k
i=0;
for k=.6:.1:10
    i=i+1;
    first=a/k^2;
    second=(w^2-b)/(w^4-k^2*c*w^2-d) ;
    third=(e*w^2-f)/(w^4-k^2*g*w^2-h);
    n(i,:)=double(solve(first-second-third, w));
end
krho1(:,1)=.6:.1:10;
r_real=real(n);
r_img=imag(n);

dat1=[krho1 r_real(:,1) r_real(:,2) r_real(:,3) r_real(:,4) r_real(:,5) r_real(:,6) r_real(:,7) r_real(:,8)];
fnameout=('stack_using_solve.dat');
fid1=fopen(fnameout,'w+');
fprintf(fid1,'krho\t RR1\t RR2\t RR3\t RR4\t RR5\t RR6\t RR7\t RR8\t \r');
fprintf(fid1,'%6.4f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f %7.10f \n',dat1');
fclose(fid1);
figure;
plot(krho1, r_real(:,1),krho1, r_real(:,2),krho1, r_real(:,3),krho1, r_real(:,4),krho1, r_real(:,5),krho1, r_real(:,6),krho1, r_real(:,7),krho1, r_real(:,8))
toc

方法1使用root命令,方法2使用symbolic和solve。我的问题如下:

  1. 您可以看到第一部分图表会在短时间内出现,第二部分图表会占用更长的时间。有没有办法提高速度?
  2. 这两个部分的情节看起来非常不同,你可能不得不相信我在从(a / k ^ 2)执行计算时犯了错误 - ((w ^ 2-b) /(W ^ 4-K ^ 2 * C 瓦特^ 2-d)) - ((E 瓦特^ 2-F)/(W ^ 4-K ^ 2 * G *瓦特^ 2 -h))(某事)w ^ 8-(别的)w ^ 6 ....-(其他的东西)w ^ 0 。我可以向你保证我说得对。如果在dat文件(stack_using_roots和stack_using_solve)中查找krho的任何特定值,您可以看到实际发生的情况。因为,假设krho = 3.6,两个dat文件中的根是相同的,但是“写入”的方式不是正确的。这就是为什么情节看起来很尴尬。简而言之,在使用'roots'命令时,解决方案以有序格式给出,另一方面在使用'solve'时,它会随机移动。真的发生了什么?有没有办法解决这个问题?
  3. 我用

    运行了程序

    i)syms w和n(i,:)= double(求解(first-second-third == 0,w));

    ii)syms w k和n(i,:)= double(求解(first-second-third == 0,w));

    iii)syms w k和n(i,:)= double(求解(第一秒 - 第三,w));

  4. 在所有这3个案例中,结果似乎相同。那么我们必须定义为符号的东西是什么?我们何时使用并且不使用表达式'== 0'?

1 个答案:

答案 0 :(得分:1)

  1. 有没有办法提高速度?
  2. 几个。一些微不足道的速度改进将来自在循环之前定义变量。最大的瓶颈是solve。不幸的是,如果事先不知道k,就没有明显的解决方案来解决你的问题,因此没有明显的方法可以将solve拉出for循环。

    1. 简而言之,在使用' root'命令,解决方案以有序的格式给出,另一方面,当使用' solve'时,它会随机移动。那是为什么?
    2. 你的函数关于w = 0是对称的。因此,对于每个根r,在-r处有另一个根。每当你调用solve时,它会给你第一个,第二个,第三个然后第四个根,然后是相同的东西,但是这次根乘以 -1。

      有时候解决选择取出-1作为一个共同因素。在这些情况下,它首先给你的根乘以-1,然后是正根。为什么它有时会取出-1,有时候不会,我不知道,但在你的情况下(因为你不关心想象的部分)你可以通过替换{{1与double(solve(first-second-third, w))一起使用。根的顺序与方法1中的顺序不一样,但是你不会得到奇怪的切换行为。

      1. 在所有这3个案例中,结果似乎相同。那么我们必须定义为符号的东西是什么?我们何时使用并且不使用表达式' == 0'?
      2. sort(real(double(solve(first-second-third, w))))syms w k相比没有什么区别,因为您将k重新定义为数值(0.6,0.7,...等)。只有syms w需要具有象征性。

        w的{​​{3}}决定了如何指定等式。如果向下滚动到有关输入变量solve的部分,则说明

          

        如果eqns的任何元素是符号表达式(没有右侧),则solve将该元素等同为0.

        这就是为什么将eqnsfirst-second-third==0写为first-second-third的第一个输入没有区别。