MOOS 0.2375
|
00001 //$$ newmatnl.cpp Non-linear optimisation 00002 00003 // Copyright (C) 1993,4,5,6: R B Davies 00004 00005 00006 #define WANT_MATH 00007 #define WANT_STREAM 00008 00009 #include "newmatap.h" 00010 #include "newmatnl.h" 00011 00012 #ifdef use_namespace 00013 namespace NEWMAT { 00014 #endif 00015 00016 00017 00018 void FindMaximum2::Fit(ColumnVector& Theta, int n_it) 00019 { 00020 Tracer tr("FindMaximum2::Fit"); 00021 enum State {Start, Restart, Continue, Interpolate, Extrapolate, 00022 Fail, Convergence}; 00023 State TheState = Start; 00024 Real z,w,x,x2,g,l1,l2,l3,d1,d2=0,d3; 00025 ColumnVector Theta1, Theta2, Theta3; 00026 int np = Theta.Nrows(); 00027 ColumnVector H1(np), H3, HP(np), K, K1(np); 00028 bool oorg, conv; 00029 int counter = 0; 00030 Theta1 = Theta; HP = 0.0; g = 0.0; 00031 00032 // This is really a set of gotos and labels, but they do not work 00033 // correctly in AT&T C++ and Sun 4.01 C++. 00034 00035 for(;;) 00036 { 00037 switch (TheState) 00038 { 00039 case Start: 00040 tr.ReName("FindMaximum2::Fit/Start"); 00041 Value(Theta1, true, l1, oorg); 00042 if (oorg) Throw(ProgramException("invalid starting value\n")); 00043 00044 case Restart: 00045 tr.ReName("FindMaximum2::Fit/ReStart"); 00046 conv = NextPoint(H1, d1); 00047 if (conv) { TheState = Convergence; break; } 00048 if (counter++ > n_it) { TheState = Fail; break; } 00049 00050 z = 1.0 / sqrt(d1); 00051 H3 = H1 * z; K = (H3 - HP) * g; HP = H3; 00052 g = 0.0; // de-activate to use curved projection 00053 if (g==0.0) K1 = 0.0; else K1 = K * 0.2 + K1 * 0.6; 00054 // (K - K1) * alpha + K1 * (1 - alpha) 00055 // = K * alpha + K1 * (1 - 2 * alpha) 00056 K = K1 * d1; g = z; 00057 00058 case Continue: 00059 tr.ReName("FindMaximum2::Fit/Continue"); 00060 Theta2 = Theta1 + H1 + K; 00061 Value(Theta2, false, l2, oorg); 00062 if (counter++ > n_it) { TheState = Fail; break; } 00063 if (oorg) 00064 { 00065 H1 *= 0.5; K *= 0.25; d1 *= 0.5; g *= 2.0; 00066 TheState = Continue; break; 00067 } 00068 d2 = LastDerivative(H1 + K * 2.0); 00069 00070 case Interpolate: 00071 tr.ReName("FindMaximum2::Fit/Interpolate"); 00072 z = d1 + d2 - 3.0 * (l2 - l1); 00073 w = z * z - d1 * d2; 00074 if (w < 0.0) { TheState = Extrapolate; break; } 00075 w = z + sqrt(w); 00076 if (1.5 * w + d1 < 0.0) 00077 { TheState = Extrapolate; break; } 00078 if (d2 > 0.0 && l2 > l1 && w > 0.0) 00079 { TheState = Extrapolate; break; } 00080 x = d1 / (w + d1); x2 = x * x; g /= x; 00081 Theta3 = Theta1 + H1 * x + K * x2; 00082 Value(Theta3, true, l3, oorg); 00083 if (counter++ > n_it) { TheState = Fail; break; } 00084 if (oorg) 00085 { 00086 if (x <= 1.0) 00087 { x *= 0.5; x2 = x*x; g *= 2.0; d1 *= x; H1 *= x; K *= x2; } 00088 else 00089 { 00090 x = 0.5 * (x-1.0); x2 = x*x; Theta1 = Theta2; 00091 H1 = (H1 + K * 2.0) * x; 00092 K *= x2; g = 0.0; d1 = x * d2; l1 = l2; 00093 } 00094 TheState = Continue; break; 00095 } 00096 00097 if (l3 >= l1 && l3 >= l2) 00098 { Theta1 = Theta3; l1 = l3; TheState = Restart; break; } 00099 00100 d3 = LastDerivative(H1 + K * 2.0); 00101 if (l1 > l2) 00102 { H1 *= x; K *= x2; Theta2 = Theta3; d1 *= x; d2 = d3*x; } 00103 else 00104 { 00105 Theta1 = Theta2; Theta2 = Theta3; 00106 x -= 1.0; x2 = x*x; g = 0.0; H1 = (H1 + K * 2.0) * x; 00107 K *= x2; l1 = l2; l2 = l3; d1 = x*d2; d2 = x*d3; 00108 if (d1 <= 0.0) { TheState = Start; break; } 00109 } 00110 TheState = Interpolate; break; 00111 00112 case Extrapolate: 00113 tr.ReName("FindMaximum2::Fit/Extrapolate"); 00114 Theta1 = Theta2; g = 0.0; K *= 4.0; H1 = (H1 * 2.0 + K); 00115 d1 = 2.0 * d2; l1 = l2; 00116 TheState = Continue; break; 00117 00118 case Fail: 00119 Throw(ConvergenceException(Theta)); 00120 00121 case Convergence: 00122 Theta = Theta1; return; 00123 } 00124 } 00125 } 00126 00127 00128 00129 void NonLinearLeastSquares::Value 00130 (const ColumnVector& Parameters, bool, Real& v, bool& oorg) 00131 { 00132 Tracer tr("NonLinearLeastSquares::Value"); 00133 Y.ReSize(n_obs); X.ReSize(n_obs,n_param); 00134 // put the fitted values in Y, the derivatives in X. 00135 Pred.Set(Parameters); 00136 if (!Pred.IsValid()) { oorg=true; return; } 00137 for (int i=1; i<=n_obs; i++) 00138 { 00139 Y(i) = Pred(i); 00140 X.Row(i) = Pred.Derivatives(); 00141 } 00142 if (!Pred.IsValid()) { oorg=true; return; } // check afterwards as well 00143 Y = *DataPointer - Y; Real ssq = Y.SumSquare(); 00144 errorvar = ssq / (n_obs - n_param); 00145 cout << "\n" << setw(15) << setprecision(10) << " " << errorvar; 00146 Derivs = Y.t() * X; // get the derivative and stash it 00147 oorg = false; v = -0.5 * ssq; 00148 } 00149 00150 bool NonLinearLeastSquares::NextPoint(ColumnVector& Adj, Real& test) 00151 { 00152 Tracer tr("NonLinearLeastSquares::NextPoint"); 00153 QRZ(X, U); QRZ(X, Y, M); // do the QR decomposition 00154 test = M.SumSquare(); 00155 cout << " " << setw(15) << setprecision(10) 00156 << test << " " << Y.SumSquare() / (n_obs - n_param); 00157 Adj = U.i() * M; 00158 if (test < errorvar * criterion) return true; 00159 else return false; 00160 } 00161 00162 Real NonLinearLeastSquares::LastDerivative(const ColumnVector& H) 00163 { return (Derivs * H).AsScalar(); } 00164 00165 void NonLinearLeastSquares::Fit(const ColumnVector& Data, 00166 ColumnVector& Parameters) 00167 { 00168 Tracer tr("NonLinearLeastSquares::Fit"); 00169 n_param = Parameters.Nrows(); n_obs = Data.Nrows(); 00170 DataPointer = &Data; 00171 FindMaximum2::Fit(Parameters, Lim); 00172 cout << "\nConverged\n"; 00173 } 00174 00175 void NonLinearLeastSquares::MakeCovariance() 00176 { 00177 if (Covariance.Nrows()==0) 00178 { 00179 UpperTriangularMatrix UI = U.i(); 00180 Covariance << UI * UI.t() * errorvar; 00181 SE << Covariance; // get diagonals 00182 for (int i = 1; i<=n_param; i++) SE(i) = sqrt(SE(i)); 00183 } 00184 } 00185 00186 void NonLinearLeastSquares::GetStandardErrors(ColumnVector& SEX) 00187 { MakeCovariance(); SEX = SE.AsColumn(); } 00188 00189 void NonLinearLeastSquares::GetCorrelations(SymmetricMatrix& Corr) 00190 { MakeCovariance(); Corr << SE.i() * Covariance * SE.i(); } 00191 00192 void NonLinearLeastSquares::GetHatDiagonal(DiagonalMatrix& Hat) const 00193 { 00194 Hat.ReSize(n_obs); 00195 for (int i = 1; i<=n_obs; i++) Hat(i) = X.Row(i).SumSquare(); 00196 } 00197 00198 00199 // the MLE_D_FI routines 00200 00201 void MLE_D_FI::Value 00202 (const ColumnVector& Parameters, bool wg, Real& v, bool& oorg) 00203 { 00204 Tracer tr("MLE_D_FI::Value"); 00205 if (!LL.IsValid(Parameters,wg)) { oorg=true; return; } 00206 v = LL.LogLikelihood(); 00207 if (!LL.IsValid()) { oorg=true; return; } // check validity again 00208 cout << "\n" << setw(20) << setprecision(10) << v; 00209 oorg = false; 00210 Derivs = LL.Derivatives(); // Get derivatives 00211 } 00212 00213 bool MLE_D_FI::NextPoint(ColumnVector& Adj, Real& test) 00214 { 00215 Tracer tr("MLE_D_FI::NextPoint"); 00216 SymmetricMatrix FI = LL.FI(); 00217 LT = Cholesky(FI); 00218 ColumnVector Adj1 = LT.i() * Derivs; 00219 Adj = LT.t().i() * Adj1; 00220 test = SumSquare(Adj1); 00221 cout << " " << setw(20) << setprecision(10) << test; 00222 return (test < Criterion); 00223 } 00224 00225 Real MLE_D_FI::LastDerivative(const ColumnVector& H) 00226 { return (Derivs.t() * H).AsScalar(); } 00227 00228 void MLE_D_FI::Fit(ColumnVector& Parameters) 00229 { 00230 Tracer tr("MLE_D_FI::Fit"); 00231 FindMaximum2::Fit(Parameters,Lim); 00232 cout << "\nConverged\n"; 00233 } 00234 00235 void MLE_D_FI::MakeCovariance() 00236 { 00237 if (Covariance.Nrows()==0) 00238 { 00239 LowerTriangularMatrix LTI = LT.i(); 00240 Covariance << LTI.t() * LTI; 00241 SE << Covariance; // get diagonal 00242 int n = Covariance.Nrows(); 00243 for (int i=1; i <= n; i++) SE(i) = sqrt(SE(i)); 00244 } 00245 } 00246 00247 void MLE_D_FI::GetStandardErrors(ColumnVector& SEX) 00248 { MakeCovariance(); SEX = SE.AsColumn(); } 00249 00250 void MLE_D_FI::GetCorrelations(SymmetricMatrix& Corr) 00251 { MakeCovariance(); Corr << SE.i() * Covariance * SE.i(); } 00252 00253 00254 00255 #ifdef use_namespace 00256 } 00257 #endif 00258