00001
00006
00007
00008 #include <fvar.hpp>
00009
00010
00011 void tri_dag(const dvar_matrix& ,const dvar_vector& ,const dvar_vector& );
00012 void get_eigen(const dvar_vector& d,const dvar_vector& e, const dvar_matrix& z);
00013
00014
00015 dvar_vector eigenvalues(const dvar_matrix& m)
00016 {
00017 if (m.rowsize()!=m.colsize())
00018 {
00019 cerr << "Error -- non square matrix passed to "
00020 "dvector eigen(const dvar_matrix& m)\n";
00021 ad_exit(1);
00022 }
00023 dvar_matrix m1=symmetrize(m);
00024 int n=m1.rowsize();
00025 m1.colshift(1);
00026 m1.rowshift(1);
00027 dvar_vector diag(1,n);
00028 dvar_vector off_diag(1,n);
00029
00030 tri_dag(m1,diag,off_diag);
00031
00032
00033 get_eigen(diag,off_diag,m1);
00034
00035
00036 return diag;
00037 }
00038
00049 void tri_dag(const dvar_matrix& _m,const dvar_vector& _d, const dvar_vector& _e)
00050 {
00051 ADUNCONST(dvar_vector,d)
00052 ADUNCONST(dvar_vector,e)
00053 dvar_matrix& m=(dvar_matrix&) _m;
00054 if (m.rowsize() != m.colsize())
00055 {
00056 cerr << "Error -- non square matrix passed to "
00057 "void tridag(const dmatrix& m)\n";
00058 ad_exit(1);
00059 }
00060 if (m.rowsize() != d.size() || m.rowsize() != e.size()
00061 || d.indexmin() != 1 || e.indexmin() !=1 )
00062 {
00063 cerr <<"Error -- incorrect vector size passed to "
00064 "void tridag(const dmatrix& m)\n";
00065 ad_exit(1);
00066 }
00067 int n=m.rowsize();
00068 int l,k,j,i;
00069 dvariable scale,hh,h,g,f;
00070
00071 for (i=n;i>=2;i--)
00072 {
00073 l=i-1;
00074 h=scale=0.0;
00075 if (l > 1)
00076 {
00077 for (k=1;k<=l;k++)
00078 scale += fabs(m[i][k]);
00079 if (scale == 0.0)
00080 e[i]=m[i][l];
00081 else
00082 {
00083 for (k=1;k<=l;k++)
00084 {
00085 m[i][k] /= scale;
00086 h += m[i][k]*m[i][k];
00087 }
00088 f=m[i][l];
00089 g = f>0. ? -sqrt(h) : sqrt(h);
00090 e[i]=scale*g;
00091 h -= f*g;
00092 m[i][l]=f-g;
00093 f=0.0;
00094 for (j=1;j<=l;j++)
00095 {
00096 #ifdef EIGEN_VECTORS
00097
00098 m[j][i]=m[i][j]/h;
00099 #endif
00100 g=0.0;
00101 for (k=1;k<=j;k++)
00102 g += m[j][k]*m[i][k];
00103 for (k=j+1;k<=l;k++)
00104 g += m[k][j]*m[i][k];
00105 e[j]=g/h;
00106 f += e[j]*m[i][j];
00107 }
00108 hh=f/(h+h);
00109 for (j=1;j<=l;j++)
00110 {
00111 f=m[i][j];
00112 e[j]=g=e[j]-hh*f;
00113 for (k=1;k<=j;k++)
00114 m[j][k] -= (f*e[k]+g*m[i][k]);
00115 }
00116 }
00117 }
00118 else
00119 {
00120 e[i]=m[i][l];
00121 }
00122 d[i]=h;
00123 }
00124
00125 d[1]=0.0;
00126 e[1]=0.0;
00127
00128
00129 #ifdef EIGEN_VECTORS
00130 for (i=1;i<=n;i++)
00131 {
00132 l=i-1;
00133 if (d[i])
00134 {
00135 for (j=1;j<=l;j++)
00136 {
00137 g=0.0;
00138 for (k=1;k<=l;k++)
00139 g += m[i][k]*m[k][j];
00140 for (k=1;k<=l;k++)
00141 m[k][j] -= g*m[k][i];
00142 }
00143 }
00144 d[i]=m[i][i];
00145 m[i][i]=1.0;
00146 for (j=1;j<=l;j++) m[j][i]=m[i][j]=0.0;
00147 }
00148 #else
00149 for (i=1;i<=n;i++)
00150 {
00151 d[i]=m[i][i];
00152 }
00153 #endif
00154 }
00155
00156 dvariable SIGN(const prevariable& x, const prevariable& y)
00157 {
00158 if (value(y) < 0)
00159 {
00160 return -fabs(x);
00161 }
00162 else
00163 {
00164 return fabs(x);
00165 }
00166 }
00167
00168
00179 void get_eigen(const dvar_vector& _d,const dvar_vector& _e,
00180 const dvar_matrix& z)
00181 {
00182 ADUNCONST(dvar_vector,d)
00183 ADUNCONST(dvar_vector,e)
00184 int n=d.size();
00185 int m,l,iter,i;
00186 dvariable s,r,p,g,f,dd,c,b;
00187
00188 for (i=2;i<=n;i++) e[i-1]=e[i];
00189 e[n]=0.0;
00190 for (l=1;l<=n;l++) {
00191 iter=0;
00192 do {
00193 for (m=l;m<=n-1;m++) {
00194 dd=fabs(d[m])+fabs(d[m+1]);
00195 if (fabs(e[m])+dd == dd) break;
00196 }
00197 if (m != l)
00198 {
00199 if (iter++ == 30)
00200 {
00201 cerr << "Maximum number of iterations exceeded in"
00202 " dvector eigen(const dmatrix& m)\n";
00203 ad_exit(1);
00204 }
00205 g=(d[l+1]-d[l])/(2.0*e[l]);
00206 r=sqrt((g*g)+1.0);
00207 g=d[m]-d[l]+e[l]/(g+SIGN(r,g));
00208 s=c=1.0;
00209 p=0.0;
00210 for (i=m-1;i>=l;i--) {
00211 f=s*e[i];
00212 b=c*e[i];
00213 if (fabs(f) >= fabs(g)) {
00214 c=g/f;
00215 r=sqrt((c*c)+1.0);
00216 e[i+1]=f*r;
00217 c *= (s=1.0/r);
00218 } else {
00219 s=f/g;
00220 r=sqrt((s*s)+1.0);
00221 e[i+1]=g*r;
00222 s *= (c=1.0/r);
00223 }
00224 g=d[i+1]-p;
00225 r=(d[i]-g)*s+2.0*c*b;
00226 p=s*r;
00227 d[i+1]=g+p;
00228 g=c*r-b;
00229
00230 #ifdef EIGEN_VECTORS
00231 for (int k=1;k<=n;k++)
00232 {
00233 f=z[k][i+1];
00234 z[k][i+1]=s*z[k][i]+c*f;
00235 z[k][i]=c*z[k][i]-s*f;
00236 }
00237 #endif
00238 }
00239 d[l]=d[l]-p;
00240 e[l]=g;
00241 e[m]=0.0;
00242 }
00243 } while (m != l);
00244 }
00245 }
00246
00258 dvar_vector get_eigen_values(const dvar_vector& _ddd,const dvar_vector& _eee)
00259 {
00260 ADUNCONST(dvar_vector,ddd)
00261 ADUNCONST(dvar_vector,eee)
00262
00263 dvar_vector d(ddd.indexmin(),ddd.indexmax());
00264 dvar_vector e(eee.indexmin(),eee.indexmax());
00265
00266 d=ddd;
00267 e=eee;
00268
00269 int n=d.size();
00270 int m,l,iter,i;
00271 dvariable s,r,p,g,f,dd,c,b;
00272
00273 for (i=2;i<=n;i++) e[i-1]=e[i];
00274 e[n]=0.0;
00275 for (l=1;l<=n;l++) {
00276 iter=0;
00277 do {
00278 for (m=l;m<=n-1;m++) {
00279 dd=fabs(d[m])+fabs(d[m+1]);
00280 if (fabs(e[m])+dd == dd) break;
00281 }
00282 if (m != l)
00283 {
00284 if (iter++ == 30)
00285 {
00286 cerr << "Maximum number of iterations exceeded in"
00287 " dvector eigen(const dmatrix& m)\n";
00288 ad_exit(1);
00289 }
00290 g=(d[l+1]-d[l])/(2.0*e[l]);
00291 r=sqrt((g*g)+1.0);
00292 g=d[m]-d[l]+e[l]/(g+SIGN(r,g));
00293 s=c=1.0;
00294 p=0.0;
00295 for (i=m-1;i>=l;i--) {
00296 f=s*e[i];
00297 b=c*e[i];
00298 if (fabs(f) >= fabs(g)) {
00299 c=g/f;
00300 r=sqrt((c*c)+1.0);
00301 e[i+1]=f*r;
00302 c *= (s=1.0/r);
00303 } else {
00304 s=f/g;
00305 r=sqrt((s*s)+1.0);
00306 e[i+1]=g*r;
00307 s *= (c=1.0/r);
00308 }
00309 g=d[i+1]-p;
00310 r=(d[i]-g)*s+2.0*c*b;
00311 p=s*r;
00312 d[i+1]=g+p;
00313 g=c*r-b;
00314
00315 }
00316 d[l]=d[l]-p;
00317 e[l]=g;
00318 e[m]=0.0;
00319 }
00320 } while (m != l);
00321 }
00322 return d;
00323 }
00324 #undef EIGEN_VECTORS