MOOS 0.2375
|
00001 //$$ example.cpp Example of use of matrix package 00002 00003 #define WANT_STREAM // include.h will get stream fns 00004 #define WANT_MATH // include.h will get math fns 00005 // newmatap.h will get include.h 00006 00007 #include "newmatap.h" // need matrix applications 00008 00009 #include "newmatio.h" // need matrix output routines 00010 00011 #ifdef use_namespace 00012 using namespace NEWMAT; // access NEWMAT namespace 00013 #endif 00014 00015 00016 // demonstration of matrix package on linear regression problem 00017 00018 00019 void test1(Real* y, Real* x1, Real* x2, int nobs, int npred) 00020 { 00021 cout << "\n\nTest 1 - traditional, bad\n"; 00022 00023 // traditional sum of squares and products method of calculation 00024 // but not adjusting means; maybe subject to round-off error 00025 00026 // make matrix of predictor values with 1s into col 1 of matrix 00027 int npred1 = npred+1; // number of cols including col of ones. 00028 Matrix X(nobs,npred1); 00029 X.Column(1) = 1.0; 00030 00031 // load x1 and x2 into X 00032 // [use << rather than = when loading arrays] 00033 X.Column(2) << x1; X.Column(3) << x2; 00034 00035 // vector of Y values 00036 ColumnVector Y(nobs); Y << y; 00037 00038 // form sum of squares and product matrix 00039 // [use << rather than = for copying Matrix into SymmetricMatrix] 00040 SymmetricMatrix SSQ; SSQ << X.t() * X; 00041 00042 // calculate estimate 00043 // [bracket last two terms to force this multiplication first] 00044 // [ .i() means inverse, but inverse is not explicity calculated] 00045 ColumnVector A = SSQ.i() * (X.t() * Y); 00046 00047 // Get variances of estimates from diagonal elements of inverse of SSQ 00048 // get inverse of SSQ - we need it for finding D 00049 DiagonalMatrix D; D << SSQ.i(); 00050 ColumnVector V = D.AsColumn(); 00051 00052 // Calculate fitted values and residuals 00053 ColumnVector Fitted = X * A; 00054 ColumnVector Residual = Y - Fitted; 00055 Real ResVar = Residual.SumSquare() / (nobs-npred1); 00056 00057 // Get diagonals of Hat matrix (an expensive way of doing this) 00058 DiagonalMatrix Hat; Hat << X * (X.t() * X).i() * X.t(); 00059 00060 // print out answers 00061 cout << "\nEstimates and their standard errors\n\n"; 00062 00063 // make vector of standard errors 00064 ColumnVector SE(npred1); 00065 for (int i=1; i<=npred1; i++) SE(i) = sqrt(V(i)*ResVar); 00066 // use concatenation function to form matrix and use matrix print 00067 // to get two columns 00068 cout << setw(11) << setprecision(5) << (A | SE) << endl; 00069 00070 cout << "\nObservations, fitted value, residual value, hat value\n"; 00071 00072 // use concatenation again; select only columns 2 to 3 of X 00073 cout << setw(9) << setprecision(3) << 00074 (X.Columns(2,3) | Y | Fitted | Residual | Hat.AsColumn()); 00075 cout << "\n\n"; 00076 } 00077 00078 void test2(Real* y, Real* x1, Real* x2, int nobs, int npred) 00079 { 00080 cout << "\n\nTest 2 - traditional, OK\n"; 00081 00082 // traditional sum of squares and products method of calculation 00083 // with subtraction of means - less subject to round-off error 00084 // than test1 00085 00086 // make matrix of predictor values 00087 Matrix X(nobs,npred); 00088 00089 // load x1 and x2 into X 00090 // [use << rather than = when loading arrays] 00091 X.Column(1) << x1; X.Column(2) << x2; 00092 00093 // vector of Y values 00094 ColumnVector Y(nobs); Y << y; 00095 00096 // make vector of 1s 00097 ColumnVector Ones(nobs); Ones = 1.0; 00098 00099 // calculate means (averages) of x1 and x2 [ .t() takes transpose] 00100 RowVector M = Ones.t() * X / nobs; 00101 00102 // and subtract means from x1 and x1 00103 Matrix XC(nobs,npred); 00104 XC = X - Ones * M; 00105 00106 // do the same to Y [use Sum to get sum of elements] 00107 ColumnVector YC(nobs); 00108 Real m = Sum(Y) / nobs; YC = Y - Ones * m; 00109 00110 // form sum of squares and product matrix 00111 // [use << rather than = for copying Matrix into SymmetricMatrix] 00112 SymmetricMatrix SSQ; SSQ << XC.t() * XC; 00113 00114 // calculate estimate 00115 // [bracket last two terms to force this multiplication first] 00116 // [ .i() means inverse, but inverse is not explicity calculated] 00117 ColumnVector A = SSQ.i() * (XC.t() * YC); 00118 00119 // calculate estimate of constant term 00120 // [AsScalar converts 1x1 matrix to Real] 00121 Real a = m - (M * A).AsScalar(); 00122 00123 // Get variances of estimates from diagonal elements of inverse of SSQ 00124 // [ we are taking inverse of SSQ - we need it for finding D ] 00125 Matrix ISSQ = SSQ.i(); DiagonalMatrix D; D << ISSQ; 00126 ColumnVector V = D.AsColumn(); 00127 Real v = 1.0/nobs + (M * ISSQ * M.t()).AsScalar(); 00128 // for calc variance of const 00129 00130 // Calculate fitted values and residuals 00131 int npred1 = npred+1; 00132 ColumnVector Fitted = X * A + a; 00133 ColumnVector Residual = Y - Fitted; 00134 Real ResVar = Residual.SumSquare() / (nobs-npred1); 00135 00136 // Get diagonals of Hat matrix (an expensive way of doing this) 00137 Matrix X1(nobs,npred1); X1.Column(1)<<Ones; X1.Columns(2,npred1)<<X; 00138 DiagonalMatrix Hat; Hat << X1 * (X1.t() * X1).i() * X1.t(); 00139 00140 // print out answers 00141 cout << "\nEstimates and their standard errors\n\n"; 00142 cout.setf(ios::fixed, ios::floatfield); 00143 cout << setw(11) << setprecision(5) << a << " "; 00144 cout << setw(11) << setprecision(5) << sqrt(v*ResVar) << endl; 00145 // make vector of standard errors 00146 ColumnVector SE(npred); 00147 for (int i=1; i<=npred; i++) SE(i) = sqrt(V(i)*ResVar); 00148 // use concatenation function to form matrix and use matrix print 00149 // to get two columns 00150 cout << setw(11) << setprecision(5) << (A | SE) << endl; 00151 cout << "\nObservations, fitted value, residual value, hat value\n"; 00152 cout << setw(9) << setprecision(3) << 00153 (X | Y | Fitted | Residual | Hat.AsColumn()); 00154 cout << "\n\n"; 00155 } 00156 00157 void test3(Real* y, Real* x1, Real* x2, int nobs, int npred) 00158 { 00159 cout << "\n\nTest 3 - Cholesky\n"; 00160 00161 // traditional sum of squares and products method of calculation 00162 // with subtraction of means - using Cholesky decomposition 00163 00164 Matrix X(nobs,npred); 00165 X.Column(1) << x1; X.Column(2) << x2; 00166 ColumnVector Y(nobs); Y << y; 00167 ColumnVector Ones(nobs); Ones = 1.0; 00168 RowVector M = Ones.t() * X / nobs; 00169 Matrix XC(nobs,npred); 00170 XC = X - Ones * M; 00171 ColumnVector YC(nobs); 00172 Real m = Sum(Y) / nobs; YC = Y - Ones * m; 00173 SymmetricMatrix SSQ; SSQ << XC.t() * XC; 00174 00175 // Cholesky decomposition of SSQ 00176 LowerTriangularMatrix L = Cholesky(SSQ); 00177 00178 // calculate estimate 00179 ColumnVector A = L.t().i() * (L.i() * (XC.t() * YC)); 00180 00181 // calculate estimate of constant term 00182 Real a = m - (M * A).AsScalar(); 00183 00184 // Get variances of estimates from diagonal elements of invoice of SSQ 00185 DiagonalMatrix D; D << L.t().i() * L.i(); 00186 ColumnVector V = D.AsColumn(); 00187 Real v = 1.0/nobs + (L.i() * M.t()).SumSquare(); 00188 00189 // Calculate fitted values and residuals 00190 int npred1 = npred+1; 00191 ColumnVector Fitted = X * A + a; 00192 ColumnVector Residual = Y - Fitted; 00193 Real ResVar = Residual.SumSquare() / (nobs-npred1); 00194 00195 // Get diagonals of Hat matrix (an expensive way of doing this) 00196 Matrix X1(nobs,npred1); X1.Column(1)<<Ones; X1.Columns(2,npred1)<<X; 00197 DiagonalMatrix Hat; Hat << X1 * (X1.t() * X1).i() * X1.t(); 00198 00199 // print out answers 00200 cout << "\nEstimates and their standard errors\n\n"; 00201 cout.setf(ios::fixed, ios::floatfield); 00202 cout << setw(11) << setprecision(5) << a << " "; 00203 cout << setw(11) << setprecision(5) << sqrt(v*ResVar) << endl; 00204 ColumnVector SE(npred); 00205 for (int i=1; i<=npred; i++) SE(i) = sqrt(V(i)*ResVar); 00206 cout << setw(11) << setprecision(5) << (A | SE) << endl; 00207 cout << "\nObservations, fitted value, residual value, hat value\n"; 00208 cout << setw(9) << setprecision(3) << 00209 (X | Y | Fitted | Residual | Hat.AsColumn()); 00210 cout << "\n\n"; 00211 } 00212 00213 void test4(Real* y, Real* x1, Real* x2, int nobs, int npred) 00214 { 00215 cout << "\n\nTest 4 - QR triangularisation\n"; 00216 00217 // QR triangularisation method 00218 00219 // load data - 1s into col 1 of matrix 00220 int npred1 = npred+1; 00221 Matrix X(nobs,npred1); ColumnVector Y(nobs); 00222 X.Column(1) = 1.0; X.Column(2) << x1; X.Column(3) << x2; Y << y; 00223 00224 // do Householder triangularisation 00225 // no need to deal with constant term separately 00226 Matrix X1 = X; // Want copy of matrix 00227 ColumnVector Y1 = Y; 00228 UpperTriangularMatrix U; ColumnVector M; 00229 QRZ(X1, U); QRZ(X1, Y1, M); // Y1 now contains resids 00230 ColumnVector A = U.i() * M; 00231 ColumnVector Fitted = X * A; 00232 Real ResVar = Y1.SumSquare() / (nobs-npred1); 00233 00234 // get variances of estimates 00235 U = U.i(); DiagonalMatrix D; D << U * U.t(); 00236 00237 // Get diagonals of Hat matrix 00238 DiagonalMatrix Hat; Hat << X1 * X1.t(); 00239 00240 // print out answers 00241 cout << "\nEstimates and their standard errors\n\n"; 00242 ColumnVector SE(npred1); 00243 for (int i=1; i<=npred1; i++) SE(i) = sqrt(D(i)*ResVar); 00244 cout << setw(11) << setprecision(5) << (A | SE) << endl; 00245 cout << "\nObservations, fitted value, residual value, hat value\n"; 00246 cout << setw(9) << setprecision(3) << 00247 (X.Columns(2,3) | Y | Fitted | Y1 | Hat.AsColumn()); 00248 cout << "\n\n"; 00249 } 00250 00251 void test5(Real* y, Real* x1, Real* x2, int nobs, int npred) 00252 { 00253 cout << "\n\nTest 5 - singular value\n"; 00254 00255 // Singular value decomposition method 00256 00257 // load data - 1s into col 1 of matrix 00258 int npred1 = npred+1; 00259 Matrix X(nobs,npred1); ColumnVector Y(nobs); 00260 X.Column(1) = 1.0; X.Column(2) << x1; X.Column(3) << x2; Y << y; 00261 00262 // do SVD 00263 Matrix U, V; DiagonalMatrix D; 00264 SVD(X,D,U,V); // X = U * D * V.t() 00265 ColumnVector Fitted = U.t() * Y; 00266 ColumnVector A = V * ( D.i() * Fitted ); 00267 Fitted = U * Fitted; 00268 ColumnVector Residual = Y - Fitted; 00269 Real ResVar = Residual.SumSquare() / (nobs-npred1); 00270 00271 // get variances of estimates 00272 D << V * (D * D).i() * V.t(); 00273 00274 // Get diagonals of Hat matrix 00275 DiagonalMatrix Hat; Hat << U * U.t(); 00276 00277 // print out answers 00278 cout << "\nEstimates and their standard errors\n\n"; 00279 ColumnVector SE(npred1); 00280 for (int i=1; i<=npred1; i++) SE(i) = sqrt(D(i)*ResVar); 00281 cout << setw(11) << setprecision(5) << (A | SE) << endl; 00282 cout << "\nObservations, fitted value, residual value, hat value\n"; 00283 cout << setw(9) << setprecision(3) << 00284 (X.Columns(2,3) | Y | Fitted | Residual | Hat.AsColumn()); 00285 cout << "\n\n"; 00286 } 00287 00288 int main() 00289 { 00290 cout << "\nDemonstration of Matrix package\n"; 00291 cout << "\nPrint a real number (may help lost memory test): " << 3.14159265 << "\n"; 00292 00293 // Test for any memory not deallocated after running this program 00294 Real* s1; { ColumnVector A(8000); s1 = A.Store(); } 00295 00296 { 00297 // the data 00298 00299 #ifndef ATandT 00300 Real y[] = { 8.3, 5.5, 8.0, 8.5, 5.7, 4.4, 6.3, 7.9, 9.1 }; 00301 Real x1[] = { 2.4, 1.8, 2.4, 3.0, 2.0, 1.2, 2.0, 2.7, 3.6 }; 00302 Real x2[] = { 1.7, 0.9, 1.6, 1.9, 0.5, 0.6, 1.1, 1.0, 0.5 }; 00303 #else // for compilers that do not understand aggregrates 00304 Real y[9], x1[9], x2[9]; 00305 y[0]=8.3; y[1]=5.5; y[2]=8.0; y[3]=8.5; y[4]=5.7; 00306 y[5]=4.4; y[6]=6.3; y[7]=7.9; y[8]=9.1; 00307 x1[0]=2.4; x1[1]=1.8; x1[2]=2.4; x1[3]=3.0; x1[4]=2.0; 00308 x1[5]=1.2; x1[6]=2.0; x1[7]=2.7; x1[8]=3.6; 00309 x2[0]=1.7; x2[1]=0.9; x2[2]=1.6; x2[3]=1.9; x2[4]=0.5; 00310 x2[5]=0.6; x2[6]=1.1; x2[7]=1.0; x2[8]=0.5; 00311 #endif 00312 00313 int nobs = 9; // number of observations 00314 int npred = 2; // number of predictor values 00315 00316 // we want to find the values of a,a1,a2 to give the best 00317 // fit of y[i] with a0 + a1*x1[i] + a2*x2[i] 00318 // Also print diagonal elements of hat matrix, X*(X.t()*X).i()*X.t() 00319 00320 // this example demonstrates five methods of calculation 00321 00322 Try 00323 { 00324 test1(y, x1, x2, nobs, npred); 00325 test2(y, x1, x2, nobs, npred); 00326 test3(y, x1, x2, nobs, npred); 00327 test4(y, x1, x2, nobs, npred); 00328 test5(y, x1, x2, nobs, npred); 00329 } 00330 CatchAll { cout << Exception::what(); } 00331 } 00332 00333 #ifdef DO_FREE_CHECK 00334 FreeCheck::Status(); 00335 #endif 00336 Real* s2; { ColumnVector A(8000); s2 = A.Store(); } 00337 cout << "\n\nThe following test does not work with all compilers - see documentation\n"; 00338 cout << "Checking for lost memory: " 00339 << (unsigned long)s1 << " " << (unsigned long)s2 << " "; 00340 if (s1 != s2) cout << " - error\n"; else cout << " - ok\n"; 00341 00342 return 0; 00343 00344 } 00345