• 数值计算程序特征值和特征向量 [转]


      1 //数值计算程序-特征值和特征向量 
      2 
      3 ////////////////////////////////////////////////////////////// 
      4 //约化对称矩阵为三对角对称矩阵 
      5 //利用Householder变换将n阶实对称矩阵约化为对称三对角矩阵 
      6 //a-长度为n*n的数组,存放n阶实对称矩阵 
      7 //n-矩阵的阶数 
      8 //q-长度为n*n的数组,返回时存放Householder变换矩阵 
      9 //b-长度为n的数组,返回时存放三对角阵的主对角线元素 
     10 //c-长度为n的数组,返回时前n-1个元素存放次对角线元素 
     11 void eastrq(double a[],int n,double q[],double b[],double c[]); 
     12 ////////////////////////////////////////////////////////////// 
     13 //求实对称三对角对称矩阵的全部特征值及特征向量 
     14 //利用变型QR方法计算实对称三对角矩阵全部特征值及特征向量 
     15 //n-矩阵的阶数 
     16 //b-长度为n的数组,返回时存放三对角阵的主对角线元素 
     17 //c-长度为n的数组,返回时前n-1个元素存放次对角线元素 
     18 //q-长度为n*n的数组,若存放单位矩阵,则返回实对称三对角矩阵的特征向量组 
     19 // 若存放Householder变换矩阵,则返回实对称矩阵A的特征向量组 
     20 //a-长度为n*n的数组,存放n阶实对称矩阵 
     21 int ebstq(int n,double b[],double c[],double q[],double eps,int l); 
     22 ////////////////////////////////////////////////////////////// 
     23 //约化实矩阵为赫申伯格(Hessen berg)矩阵 
     24 //利用初等相似变换将n阶实矩阵约化为上H矩阵 
     25 //a-长度为n*n的数组,存放n阶实矩阵,返回时存放上H矩阵 
     26 //n-矩阵的阶数 
     27 void echbg(double a[],int n); 
     28 ////////////////////////////////////////////////////////////// 
     29 //求赫申伯格(Hessen berg)矩阵的全部特征值 
     30 //返回值小于0表示超过迭代jt次仍未达到精度要求 
     31 //返回值大于0表示正常返回 
     32 //利用带原点位移的双重步QR方法求上H矩阵的全部特征值 
     33 //a-长度为n*n的数组,存放上H矩阵 
     34 //n-矩阵的阶数 
     35 //u-长度为n的数组,返回n个特征值的实部 
     36 //v-长度为n的数组,返回n个特征值的虚部 
     37 //eps-控制精度要求 
     38 //jt-整型变量,控制最大迭代次数 
     39 int edqr(double a[],int n,double u[],double v[],double eps,int jt); 
     40 ////////////////////////////////////////////////////////////// 
     41 //求实对称矩阵的特征值及特征向量的雅格比法 
     42 //利用雅格比(Jacobi)方法求实对称矩阵的全部特征值及特征向量 
     43 //返回值小于0表示超过迭代jt次仍未达到精度要求 
     44 //返回值大于0表示正常返回 
     45 //a-长度为n*n的数组,存放实对称矩阵,返回时对角线存放n个特征值 
     46 //n-矩阵的阶数 
     47 //u-长度为n*n的数组,返回特征向量(按列存储) 
     48 //eps-控制精度要求 
     49 //jt-整型变量,控制最大迭代次数 
     50 int eejcb(double a[],int n,double v[],double eps,int jt); 
     51 ////////////////////////////////////////////////////////////// 
     52 
     53 
     54 
     55 选自<<徐世良数值计算程序集(C)>> 
     56 
     57 每个程序都加上了适当地注释,陆陆续续干了几个月才整理出来的啊。 
     58 
     59 今天都给贴出来了 
     60 
     61 #include "stdio.h" 
     62 #include "math.h" 
     63 //约化对称矩阵为三对角对称矩阵 
     64 //利用Householder变换将n阶实对称矩阵约化为对称三对角矩阵 
     65 //a-长度为n*n的数组,存放n阶实对称矩阵 
     66 //n-矩阵的阶数 
     67 //q-长度为n*n的数组,返回时存放Householder变换矩阵 
     68 //b-长度为n的数组,返回时存放三对角阵的主对角线元素 
     69 //c-长度为n的数组,返回时前n-1个元素存放次对角线元素 
     70 void eastrq(double a[],int n,double q[],double b[],double c[]) 
     71 { 
     72 int i,j,k,u,v; 
     73 double h,f,g,h2; 
     74 for (i=0; i<=n-1; i++) 
     75 { 
     76 for (j=0; j<=n-1; j++) 
     77 { 
     78 u=i*n+j; q[u]=a[u]; 
     79 } 
     80 } 
     81 for (i=n-1; i>=1; i--) 
     82 { 
     83 h=0.0; 
     84 if (i>1) 
     85 { 
     86 for (k=0; k<=i-1; k++) 
     87 { 
     88 u=i*n+k; 
     89 h=h+q[u]*q[u]; 
     90 } 
     91 } 
     92 
     93 if (h+1.0==1.0) 
     94 { 
     95 c[i-1]=0.0; 
     96 if (i==1) 
     97 { 
     98 c[i-1]=q[i*n+i-1]; 
     99 } 
    100 b[i]=0.0; 
    101 } 
    102 else 
    103 { 
    104 c[i-1]=sqrt(h); 
    105 u=i*n+i-1; 
    106 if (q[u]>0.0) 
    107 { 
    108 c[i-1]=-c[i-1]; 
    109 } 
    110 h=h-q[u]*c[i-1]; 
    111 q[u]=q[u]-c[i-1]; 
    112 f=0.0; 
    113 for (j=0; j<=i-1; j++) 
    114 { 
    115 q[j*n+i]=q[i*n+j]/h; 
    116 g=0.0; 
    117 for (k=0; k<=j; k++) 
    118 { 
    119 g=g+q[j*n+k]*q[i*n+k]; 
    120 } 
    121 if (j+1<=i-1) 
    122 { 
    123 for (k=j+1; k<=i-1; k++) 
    124 { 
    125 g=g+q[k*n+j]*q[i*n+k]; 
    126 } 
    127 } 
    128 c[j-1]=g/h; 
    129 f=f+g*q[j*n+i]; 
    130 } 
    131 h2=f/(h+h); 
    132 for (j=0; j<=i-1; j++) 
    133 { 
    134 f=q[i*n+j]; 
    135 g=c[j-1]-h2*f; 
    136 c[j-1]=g; 
    137 for (k=0; k<=j; k++) 
    138 { 
    139 u=j*n+k; 
    140 q[u]=q[u]-f*c[k-1]-g*q[i*n+k]; 
    141 } 
    142 } 
    143 b[i]=h; 
    144 } 
    145 } 
    146 b[0]=0.0; 
    147 for (i=0; i<=n-1; i++) 
    148 { 
    149 if ((b[i]!=0.0)&&(i-1>=0)) 
    150 { 
    151 for (j=0; j<=i-1; j++) 
    152 { 
    153 g=0.0; 
    154 for (k=0; k<=i-1; k++) 
    155 { 
    156 g=g+q[i*n+k]*q[k*n+j]; 
    157 } 
    158 for (k=0; k<=i-1; k++) 
    159 { 
    160 u=k*n+j; 
    161 q[u]=q[u]-g*q[k*n+i]; 
    162 } 
    163 } 
    164 } 
    165 u=i*n+i; 
    166 b[i]=q[u]; 
    167 q[u]=1.0; 
    168 if (i-1>=0) 
    169 { 
    170 for (j=0; j<=i-1; j++) 
    171 { 
    172 q[i*n+j]=0.0; 
    173 q[j*n+i]=0.0; 
    174 } 
    175 } 
    176 } 
    177 return; 
    178 
    179 
    180 
    181 
    182 //求实对称三对角对称矩阵的全部特征值及特征向量 
    183 //利用变型QR方法计算实对称三对角矩阵全部特征值及特征向量 
    184 //n-矩阵的阶数 
    185 //b-长度为n的数组,返回时存放三对角阵的主对角线元素 
    186 //c-长度为n的数组,返回时前n-1个元素存放次对角线元素 
    187 //q-长度为n*n的数组,若存放单位矩阵,则返回实对称三对角矩阵的特征向量组 
    188 // 若存放Householder变换矩阵,则返回实对称矩阵A的特征向量组 
    189 //a-长度为n*n的数组,存放n阶实对称矩阵 
    190 int ebstq(int n,double b[],double c[],double q[],double eps,int l) 
    191 { 
    192 int i,j,k,m,it,u,v; 
    193 double d,f,h,g,p,r,e,s; 
    194 c[n-1]=0.0; 
    195 d=0.0; 
    196 f=0.0; 
    197 for (j=0; j<=n-1; j++) 
    198 { 
    199 it=0; 
    200 h=eps*(fabs(b[j])+fabs(c[j])); 
    201 if (h>d) 
    202 { 
    203 d=h; 
    204 } 
    205 m=j; 
    206 while ((m<=n-1)&&(fabs(c[m])>d)) 
    207 { 
    208 m=m+1; 
    209 } 
    210 if (m!=j) 
    211 { 
    212 do 
    213 { 
    214 if (it==l) 
    215 { 
    216 printf("fail\n"); 
    217 return(-1); 
    218 } 
    219 it=it+1; 
    220 g=b[j]; 
    221 p=(b[j+1]-g)/(2.0*c[j]); 
    222 r=sqrt(p*p+1.0); 
    223 if (p>=0.0) 
    224 { 
    225 b[j]=c[j]/(p+r); 
    226 } 
    227 else 
    228 { 
    229 b[j]=c[j]/(p-r); 
    230 } 
    231 h=g-b[j]; 
    232 for (i=j+1; i<=n-1; i++) 
    233 { 
    234 b[i]=b[i]-h; 
    235 } 
    236 f=f+h; 
    237 p=b[m]; 
    238 e=1.0; 
    239 s=0.0; 
    240 for (i=m-1; i>=j; i--) 
    241 { 
    242 g=e*c[i]; 
    243 h=e*p; 
    244 if (fabs(p)>=fabs(c[i])) 
    245 { 
    246 e=c[i]/p; 
    247 r=sqrt(e*e+1.0); 
    248 c[i+1]=s*p*r; 
    249 s=e/r; 
    250 e=1.0/r; 
    251 } 
    252 else 
    253 { 
    254 e=p/c[i]; 
    255 r=sqrt(e*e+1.0); 
    256 c[i+1]=s*c[i]*r; 
    257 s=1.0/r; 
    258 e=e/r; 
    259 } 
    260 p=e*b[i]-s*g; 
    261 b[i+1]=h+s*(e*g+s*b[i]); 
    262 for (k=0; k<=n-1; k++) 
    263 { 
    264 u=k*n+i+1; 
    265 v=u-1; 
    266 h=q[u]; 
    267 q[u]=s*q[v]+e*h; 
    268 q[v]=e*q[v]-s*h; 
    269 } 
    270 } 
    271 c[j]=s*p; 
    272 b[j]=e*p; 
    273 } 
    274 while (fabs(c[j])>d); 
    275 } 
    276 b[j]=b[j]+f; 
    277 } 
    278 for (i=0; i<=n-1; i++) 
    279 { 
    280 k=i; p=b[i]; 
    281 if (i+1<=n-1) 
    282 { 
    283 j=i+1; 
    284 while ((j<=n-1)&&(b[j]<=p)) 
    285 { 
    286 k=j; 
    287 p=b[j]; 
    288 j=j+1; 
    289 } 
    290 } 
    291 if (k!=i) 
    292 { 
    293 b[k]=b[i]; 
    294 b[i]=p; 
    295 for (j=0; j<=n-1; j++) 
    296 { 
    297 u=j*n+i; 
    298 v=j*n+k; 
    299 p=q[u]; 
    300 q[u]=q[v]; 
    301 q[v]=p; 
    302 } 
    303 } 
    304 } 
    305 return(1); 
    306 } 
    307 
    308 //约化实矩阵为赫申伯格(Hessen berg)矩阵 
    309 //利用初等相似变换将n阶实矩阵约化为上H矩阵 
    310 //a-长度为n*n的数组,存放n阶实矩阵,返回时存放上H矩阵 
    311 //n-矩阵的阶数 
    312 void echbg(double a[],int n) 
    313 { int i,j,k,u,v; 
    314 double d,t; 
    315 for (k=1; k<=n-2; k++) 
    316 { 
    317 d=0.0; 
    318 for (j=k; j<=n-1; j++) 
    319 { 
    320 u=j*n+k-1; 
    321 t=a[u]; 
    322 if (fabs(t)>fabs(d)) 
    323 { 
    324 d=t; 
    325 i=j; 
    326 } 
    327 } 
    328 if (fabs(d)+1.0!=1.0) 
    329 { 
    330 if (i!=k) 
    331 { 
    332 for (j=k-1; j<=n-1; j++) 
    333 { 
    334 u=i*n+j; 
    335 v=k*n+j; 
    336 t=a[u]; 
    337 a[u]=a[v]; 
    338 a[v]=t; 
    339 } 
    340 for (j=0; j<=n-1; j++) 
    341 { 
    342 u=j*n+i; 
    343 v=j*n+k; 
    344 t=a[u]; 
    345 a[u]=a[v]; 
    346 a[v]=t; 
    347 } 
    348 } 
    349 for (i=k+1; i<=n-1; i++) 
    350 { 
    351 u=i*n+k-1; 
    352 t=a[u]/d; 
    353 a[u]=0.0; 
    354 for (j=k; j<=n-1; j++) 
    355 { 
    356 v=i*n+j; 
    357 a[v]=a[v]-t*a[k*n+j]; 
    358 } 
    359 for (j=0; j<=n-1; j++) 
    360 { 
    361 v=j*n+k; 
    362 a[v]=a[v]+t*a[j*n+i]; 
    363 } 
    364 } 
    365 } 
    366 } 
    367 return; 
    368 } 
    369 
    370 
    371 
    372 //求赫申伯格(Hessen berg)矩阵的全部特征值 
    373 //利用带原点位移的双重步QR方法求上H矩阵的全部特征值 
    374 //返回值小于0表示超过迭代jt次仍未达到精度要求 
    375 //返回值大于0表示正常返回 
    376 //a-长度为n*n的数组,存放上H矩阵 
    377 //n-矩阵的阶数 
    378 //u-长度为n的数组,返回n个特征值的实部 
    379 //v-长度为n的数组,返回n个特征值的虚部 
    380 //eps-控制精度要求 
    381 //jt-整型变量,控制最大迭代次数 
    382 int edqr(double a[],int n,double u[],double v[],double eps,int jt) 
    383 { 
    384 int m,it,i,j,k,l,ii,jj,kk,ll; 
    385 double b,c,w,g,xy,p,q,r,x,s,e,f,z,y; 
    386 it=0; 
    387 m=n; 
    388 while (m!=0) 
    389 { 
    390 l=m-1; 
    391 while ((l>0)&&(fabs(a[l*n+l-1])>eps*(fabs(a[(l-1)*n+l-1])+fabs(a[l*n+l])))) 
    392 { 
    393 l=l-1; 
    394 } 
    395 ii=(m-1)*n+m-1; 
    396 jj=(m-1)*n+m-2; 
    397 kk=(m-2)*n+m-1; 
    398 ll=(m-2)*n+m-2; 
    399 if (l==m-1) 
    400 { 
    401 u[m-1]=a[(m-1)*n+m-1]; 
    402 v[m-1]=0.0; 
    403 m=m-1; it=0; 
    404 } 
    405 else if (l==m-2) 
    406 { 
    407 b=-(a[ii]+a[ll]); 
    408 c=a[ii]*a[ll]-a[jj]*a[kk]; 
    409 w=b*b-4.0*c; 
    410 y=sqrt(fabs(w)); 
    411 if (w>0.0) 
    412 { 
    413 xy=1.0; 
    414 if (b<0.0) 
    415 { 
    416 xy=-1.0; 
    417 } 
    418 u[m-1]=(-b-xy*y)/2.0; 
    419 u[m-2]=c/u[m-1]; 
    420 v[m-1]=0.0; v[m-2]=0.0; 
    421 } 
    422 else 
    423 { 
    424 u[m-1]=-b/2.0; 
    425 u[m-2]=u[m-1]; 
    426 v[m-1]=y/2.0; 
    427 v[m-2]=-v[m-1]; 
    428 } 
    429 m=m-2; 
    430 it=0; 
    431 } 
    432 else 
    433 { 
    434 if (it>=jt) 
    435 { 
    436 printf("fail\n"); 
    437 return(-1); 
    438 } 
    439 it=it+1; 
    440 for (j=l+2; j<=m-1; j++) 
    441 { 
    442 a[j*n+j-2]=0.0; 
    443 } 
    444 for (j=l+3; j<=m-1; j++) 
    445 { 
    446 a[j*n+j-3]=0.0; 
    447 } 
    448 for (k=l; k<=m-2; k++) 
    449 { 
    450 if (k!=l) 
    451 { 
    452 p=a[k*n+k-1]; 
    453 q=a[(k+1)*n+k-1]; 
    454 r=0.0; 
    455 if (k!=m-2) 
    456 { 
    457 r=a[(k+2)*n+k-1]; 
    458 } 
    459 } 
    460 else 
    461 { 
    462 x=a[ii]+a[ll]; 
    463 y=a[ll]*a[ii]-a[kk]*a[jj]; 
    464 ii=l*n+l; 
    465 jj=l*n+l+1; 
    466 kk=(l+1)*n+l; 
    467 ll=(l+1)*n+l+1; 
    468 p=a[ii]*(a[ii]-x)+a[jj]*a[kk]+y; 
    469 q=a[kk]*(a[ii]+a[ll]-x); 
    470 r=a[kk]*a[(l+2)*n+l+1]; 
    471 } 
    472 if ((fabs(p)+fabs(q)+fabs(r))!=0.0) 
    473 { 
    474 xy=1.0; 
    475 if (p<0.0) 
    476 { 
    477 xy=-1.0; 
    478 } 
    479 s=xy*sqrt(p*p+q*q+r*r); 
    480 if (k!=l) 
    481 { 
    482 a[k*n+k-1]=-s; 
    483 } 
    484 e=-q/s; 
    485 f=-r/s; 
    486 x=-p/s; 
    487 y=-x-f*r/(p+s); 
    488 g=e*r/(p+s); 
    489 z=-x-e*q/(p+s); 
    490 for (j=k; j<=m-1; j++) 
    491 { 
    492 ii=k*n+j; 
    493 jj=(k+1)*n+j; 
    494 p=x*a[ii]+e*a[jj]; 
    495 q=e*a[ii]+y*a[jj]; 
    496 r=f*a[ii]+g*a[jj]; 
    497 if (k!=m-2) 
    498 { 
    499 kk=(k+2)*n+j; 
    500 p=p+f*a[kk]; 
    501 q=q+g*a[kk]; 
    502 r=r+z*a[kk]; 
    503 a[kk]=r; 
    504 } 
    505 a[jj]=q; 
    506 a[ii]=p; 
    507 } 
    508 j=k+3; 
    509 if (j>=m-1) 
    510 { 
    511 j=m-1; 
    512 } 
    513 for (i=l; i<=j; i++) 
    514 { 
    515 ii=i*n+k; 
    516 jj=i*n+k+1; 
    517 p=x*a[ii]+e*a[jj]; 
    518 q=e*a[ii]+y*a[jj]; 
    519 r=f*a[ii]+g*a[jj]; 
    520 if (k!=m-2) 
    521 { 
    522 kk=i*n+k+2; 
    523 p=p+f*a[kk]; 
    524 q=q+g*a[kk]; 
    525 r=r+z*a[kk]; 
    526 a[kk]=r; 
    527 } 
    528 a[jj]=q; 
    529 a[ii]=p; 
    530 } 
    531 } 
    532 } 
    533 } 
    534 } 
    535 return(1); 
    536 } 
    537 
    538 
    539 
    540 //求实对称矩阵的特征值及特征向量的雅格比法 
    541 //利用雅格比(Jacobi)方法求实对称矩阵的全部特征值及特征向量 
    542 //返回值小于0表示超过迭代jt次仍未达到精度要求 
    543 //返回值大于0表示正常返回 
    544 //a-长度为n*n的数组,存放实对称矩阵,返回时对角线存放n个特征值 
    545 //n-矩阵的阶数 
    546 //u-长度为n*n的数组,返回特征向量(按列存储) 
    547 //eps-控制精度要求 
    548 //jt-整型变量,控制最大迭代次数 
    549 int eejcb(double a[],int n,double v[],double eps,int jt) 
    550 { 
    551 int i,j,p,q,u,w,t,s,l; 
    552 double fm,cn,sn,omega,x,y,d; 
    553 l=1; 
    554 for (i=0; i<=n-1; i++) 
    555 { 
    556 v[i*n+i]=1.0; 
    557 for (j=0; j<=n-1; j++) 
    558 { 
    559 if (i!=j) 
    560 { 
    561 v[i*n+j]=0.0; 
    562 } 
    563 } 
    564 } 
    565 while (1==1) 
    566 { 
    567 fm=0.0; 
    568 for (i=0; i<=n-1; i++) 
    569 { 
    570 for (j=0; j<=n-1; j++) 
    571 { 
    572 d=fabs(a[i*n+j]); 
    573 if ((i!=j)&&(d>fm)) 
    574 { 
    575 fm=d; 
    576 p=i; 
    577 q=j; 
    578 } 
    579 } 
    580 } 
    581 if (fm<eps) 
    582 { 
    583 return(1); 
    584 } 
    585 if (l>jt) 
    586 { 
    587 return(-1); 
    588 } 
    589 l=l+1; 
    590 u=p*n+q; 
    591 w=p*n+p; 
    592 t=q*n+p; 
    593 s=q*n+q; 
    594 x=-a[u]; 
    595 y=(a[s]-a[w])/2.0; 
    596 omega=x/sqrt(x*x+y*y); 
    597 if (y<0.0) 
    598 { 
    599 omega=-omega; 
    600 } 
    601 sn=1.0+sqrt(1.0-omega*omega); 
    602 sn=omega/sqrt(2.0*sn); 
    603 cn=sqrt(1.0-sn*sn); 
    604 fm=a[w]; 
    605 a[w]=fm*cn*cn+a[s]*sn*sn+a[u]*omega; 
    606 a[s]=fm*sn*sn+a[s]*cn*cn-a[u]*omega; 
    607 a[u]=0.0; 
    608 a[t]=0.0; 
    609 for (j=0; j<=n-1; j++) 
    610 { 
    611 if ((j!=p)&&(j!=q)) 
    612 { 
    613 u=p*n+j; 
    614 w=q*n+j; 
    615 fm=a[u]; 
    616 a[u]=fm*cn+a[w]*sn; 
    617 a[w]=-fm*sn+a[w]*cn; 
    618 } 
    619 } 
    620 for (i=0; i<=n-1; i++) 
    621 { 
    622 if ((i!=p)&&(i!=q)) 
    623 { 
    624 u=i*n+p; 
    625 w=i*n+q; 
    626 fm=a[u]; 
    627 a[u]=fm*cn+a[w]*sn; 
    628 a[w]=-fm*sn+a[w]*cn; 
    629 } 
    630 } 
    631 for (i=0; i<=n-1; i++) 
    632 { 
    633 u=i*n+p; 
    634 w=i*n+q; 
    635 fm=v[u]; 
    636 v[u]=fm*cn+v[w]*sn; 
    637 v[w]=-fm*sn+v[w]*cn; 
    638 } 
    639 } 
    640 return(1); 
    641 }
  • 相关阅读:
    luoguP3402 最长公共子序列(LCS-->LIS)
    luoguP3402 最长公共子序列(LCS-->LIS)
    日常(关于机房卫生???)
    1.STL list
    21.优先队列的实现
    20.链式队列
    19.链式栈
    18.链表管理内存实现c语言自动释放内存
    17.环形链表,以及用环形链表解决约瑟夫问题
    16.单向链表的一些基本操作实现(链表反转,链表有环无环判断,链表冒泡排序,链表快速排序)
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2465191.html
Copyright © 2020-2023  润新知