1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
|
//$$ example.cpp Example of use of matrix package
#define WANT_STREAM // include.h will get stream fns
#define WANT_MATH // include.h will get math fns
// newmatap.h will get include.h
#include "newmatap.h" // need matrix applications
#include "newmatio.h" // need matrix output routines
#ifdef use_namespace
using namespace NEWMAT; // access NEWMAT namespace
#endif
// demonstration of matrix package on linear regression problem
void test1(Real* y, Real* x1, Real* x2, int nobs, int npred)
{
cout << "\n\nTest 1 - traditional, bad\n";
// traditional sum of squares and products method of calculation
// but not adjusting means; maybe subject to round-off error
// make matrix of predictor values with 1s into col 1 of matrix
int npred1 = npred+1; // number of cols including col of ones.
Matrix X(nobs,npred1);
X.Column(1) = 1.0;
// load x1 and x2 into X
// [use << rather than = when loading arrays]
X.Column(2) << x1; X.Column(3) << x2;
// vector of Y values
ColumnVector Y(nobs); Y << y;
// form sum of squares and product matrix
// [use << rather than = for copying Matrix into SymmetricMatrix]
SymmetricMatrix SSQ; SSQ << X.t() * X;
// calculate estimate
// [bracket last two terms to force this multiplication first]
// [ .i() means inverse, but inverse is not explicity calculated]
ColumnVector A = SSQ.i() * (X.t() * Y);
// Get variances of estimates from diagonal elements of inverse of SSQ
// get inverse of SSQ - we need it for finding D
DiagonalMatrix D; D << SSQ.i();
ColumnVector V = D.AsColumn();
// Calculate fitted values and residuals
ColumnVector Fitted = X * A;
ColumnVector Residual = Y - Fitted;
Real ResVar = Residual.SumSquare() / (nobs-npred1);
// Get diagonals of Hat matrix (an expensive way of doing this)
DiagonalMatrix Hat; Hat << X * (X.t() * X).i() * X.t();
// print out answers
cout << "\nEstimates and their standard errors\n\n";
// make vector of standard errors
ColumnVector SE(npred1);
for (int i=1; i<=npred1; i++) SE(i) = sqrt(V(i)*ResVar);
// use concatenation function to form matrix and use matrix print
// to get two columns
cout << setw(11) << setprecision(5) << (A | SE) << endl;
cout << "\nObservations, fitted value, residual value, hat value\n";
// use concatenation again; select only columns 2 to 3 of X
cout << setw(9) << setprecision(3) <<
(X.Columns(2,3) | Y | Fitted | Residual | Hat.AsColumn());
cout << "\n\n";
}
void test2(Real* y, Real* x1, Real* x2, int nobs, int npred)
{
cout << "\n\nTest 2 - traditional, OK\n";
// traditional sum of squares and products method of calculation
// with subtraction of means - less subject to round-off error
// than test1
// make matrix of predictor values
Matrix X(nobs,npred);
// load x1 and x2 into X
// [use << rather than = when loading arrays]
X.Column(1) << x1; X.Column(2) << x2;
// vector of Y values
ColumnVector Y(nobs); Y << y;
// make vector of 1s
ColumnVector Ones(nobs); Ones = 1.0;
// calculate means (averages) of x1 and x2 [ .t() takes transpose]
RowVector M = Ones.t() * X / nobs;
// and subtract means from x1 and x1
Matrix XC(nobs,npred);
XC = X - Ones * M;
// do the same to Y [use Sum to get sum of elements]
ColumnVector YC(nobs);
Real m = Sum(Y) / nobs; YC = Y - Ones * m;
// form sum of squares and product matrix
// [use << rather than = for copying Matrix into SymmetricMatrix]
SymmetricMatrix SSQ; SSQ << XC.t() * XC;
// calculate estimate
// [bracket last two terms to force this multiplication first]
// [ .i() means inverse, but inverse is not explicity calculated]
ColumnVector A = SSQ.i() * (XC.t() * YC);
// calculate estimate of constant term
// [AsScalar converts 1x1 matrix to Real]
Real a = m - (M * A).AsScalar();
// Get variances of estimates from diagonal elements of inverse of SSQ
// [ we are taking inverse of SSQ - we need it for finding D ]
Matrix ISSQ = SSQ.i(); DiagonalMatrix D; D << ISSQ;
ColumnVector V = D.AsColumn();
Real v = 1.0/nobs + (M * ISSQ * M.t()).AsScalar();
// for calc variance of const
// Calculate fitted values and residuals
int npred1 = npred+1;
ColumnVector Fitted = X * A + a;
ColumnVector Residual = Y - Fitted;
Real ResVar = Residual.SumSquare() / (nobs-npred1);
// Get diagonals of Hat matrix (an expensive way of doing this)
Matrix X1(nobs,npred1); X1.Column(1)<<Ones; X1.Columns(2,npred1)<<X;
DiagonalMatrix Hat; Hat << X1 * (X1.t() * X1).i() * X1.t();
// print out answers
cout << "\nEstimates and their standard errors\n\n";
cout.setf(ios::fixed, ios::floatfield);
cout << setw(11) << setprecision(5) << a << " ";
cout << setw(11) << setprecision(5) << sqrt(v*ResVar) << endl;
// make vector of standard errors
ColumnVector SE(npred);
for (int i=1; i<=npred; i++) SE(i) = sqrt(V(i)*ResVar);
// use concatenation function to form matrix and use matrix print
// to get two columns
cout << setw(11) << setprecision(5) << (A | SE) << endl;
cout << "\nObservations, fitted value, residual value, hat value\n";
cout << setw(9) << setprecision(3) <<
(X | Y | Fitted | Residual | Hat.AsColumn());
cout << "\n\n";
}
void test3(Real* y, Real* x1, Real* x2, int nobs, int npred)
{
cout << "\n\nTest 3 - Cholesky\n";
// traditional sum of squares and products method of calculation
// with subtraction of means - using Cholesky decomposition
Matrix X(nobs,npred);
X.Column(1) << x1; X.Column(2) << x2;
ColumnVector Y(nobs); Y << y;
ColumnVector Ones(nobs); Ones = 1.0;
RowVector M = Ones.t() * X / nobs;
Matrix XC(nobs,npred);
XC = X - Ones * M;
ColumnVector YC(nobs);
Real m = Sum(Y) / nobs; YC = Y - Ones * m;
SymmetricMatrix SSQ; SSQ << XC.t() * XC;
// Cholesky decomposition of SSQ
LowerTriangularMatrix L = Cholesky(SSQ);
// calculate estimate
ColumnVector A = L.t().i() * (L.i() * (XC.t() * YC));
// calculate estimate of constant term
Real a = m - (M * A).AsScalar();
// Get variances of estimates from diagonal elements of invoice of SSQ
DiagonalMatrix D; D << L.t().i() * L.i();
ColumnVector V = D.AsColumn();
Real v = 1.0/nobs + (L.i() * M.t()).SumSquare();
// Calculate fitted values and residuals
int npred1 = npred+1;
ColumnVector Fitted = X * A + a;
ColumnVector Residual = Y - Fitted;
Real ResVar = Residual.SumSquare() / (nobs-npred1);
// Get diagonals of Hat matrix (an expensive way of doing this)
Matrix X1(nobs,npred1); X1.Column(1)<<Ones; X1.Columns(2,npred1)<<X;
DiagonalMatrix Hat; Hat << X1 * (X1.t() * X1).i() * X1.t();
// print out answers
cout << "\nEstimates and their standard errors\n\n";
cout.setf(ios::fixed, ios::floatfield);
cout << setw(11) << setprecision(5) << a << " ";
cout << setw(11) << setprecision(5) << sqrt(v*ResVar) << endl;
ColumnVector SE(npred);
for (int i=1; i<=npred; i++) SE(i) = sqrt(V(i)*ResVar);
cout << setw(11) << setprecision(5) << (A | SE) << endl;
cout << "\nObservations, fitted value, residual value, hat value\n";
cout << setw(9) << setprecision(3) <<
(X | Y | Fitted | Residual | Hat.AsColumn());
cout << "\n\n";
}
void test4(Real* y, Real* x1, Real* x2, int nobs, int npred)
{
cout << "\n\nTest 4 - QR triangularisation\n";
// QR triangularisation method
// load data - 1s into col 1 of matrix
int npred1 = npred+1;
Matrix X(nobs,npred1); ColumnVector Y(nobs);
X.Column(1) = 1.0; X.Column(2) << x1; X.Column(3) << x2; Y << y;
// do Householder triangularisation
// no need to deal with constant term separately
Matrix X1 = X; // Want copy of matrix
ColumnVector Y1 = Y;
UpperTriangularMatrix U; ColumnVector M;
QRZ(X1, U); QRZ(X1, Y1, M); // Y1 now contains resids
ColumnVector A = U.i() * M;
ColumnVector Fitted = X * A;
Real ResVar = Y1.SumSquare() / (nobs-npred1);
// get variances of estimates
U = U.i(); DiagonalMatrix D; D << U * U.t();
// Get diagonals of Hat matrix
DiagonalMatrix Hat; Hat << X1 * X1.t();
// print out answers
cout << "\nEstimates and their standard errors\n\n";
ColumnVector SE(npred1);
for (int i=1; i<=npred1; i++) SE(i) = sqrt(D(i)*ResVar);
cout << setw(11) << setprecision(5) << (A | SE) << endl;
cout << "\nObservations, fitted value, residual value, hat value\n";
cout << setw(9) << setprecision(3) <<
(X.Columns(2,3) | Y | Fitted | Y1 | Hat.AsColumn());
cout << "\n\n";
}
void test5(Real* y, Real* x1, Real* x2, int nobs, int npred)
{
cout << "\n\nTest 5 - singular value\n";
// Singular value decomposition method
// load data - 1s into col 1 of matrix
int npred1 = npred+1;
Matrix X(nobs,npred1); ColumnVector Y(nobs);
X.Column(1) = 1.0; X.Column(2) << x1; X.Column(3) << x2; Y << y;
// do SVD
Matrix U, V; DiagonalMatrix D;
SVD(X,D,U,V); // X = U * D * V.t()
ColumnVector Fitted = U.t() * Y;
ColumnVector A = V * ( D.i() * Fitted );
Fitted = U * Fitted;
ColumnVector Residual = Y - Fitted;
Real ResVar = Residual.SumSquare() / (nobs-npred1);
// get variances of estimates
D << V * (D * D).i() * V.t();
// Get diagonals of Hat matrix
DiagonalMatrix Hat; Hat << U * U.t();
// print out answers
cout << "\nEstimates and their standard errors\n\n";
ColumnVector SE(npred1);
for (int i=1; i<=npred1; i++) SE(i) = sqrt(D(i)*ResVar);
cout << setw(11) << setprecision(5) << (A | SE) << endl;
cout << "\nObservations, fitted value, residual value, hat value\n";
cout << setw(9) << setprecision(3) <<
(X.Columns(2,3) | Y | Fitted | Residual | Hat.AsColumn());
cout << "\n\n";
}
int main()
{
cout << "\nDemonstration of Matrix package\n";
cout << "\nPrint a real number (may help lost memory test): " << 3.14159265 << "\n";
// Test for any memory not deallocated after running this program
Real* s1; { ColumnVector A(8000); s1 = A.Store(); }
{
// the data
#ifndef ATandT
Real y[] = { 8.3, 5.5, 8.0, 8.5, 5.7, 4.4, 6.3, 7.9, 9.1 };
Real x1[] = { 2.4, 1.8, 2.4, 3.0, 2.0, 1.2, 2.0, 2.7, 3.6 };
Real x2[] = { 1.7, 0.9, 1.6, 1.9, 0.5, 0.6, 1.1, 1.0, 0.5 };
#else // for compilers that do not understand aggregrates
Real y[9], x1[9], x2[9];
y[0]=8.3; y[1]=5.5; y[2]=8.0; y[3]=8.5; y[4]=5.7;
y[5]=4.4; y[6]=6.3; y[7]=7.9; y[8]=9.1;
x1[0]=2.4; x1[1]=1.8; x1[2]=2.4; x1[3]=3.0; x1[4]=2.0;
x1[5]=1.2; x1[6]=2.0; x1[7]=2.7; x1[8]=3.6;
x2[0]=1.7; x2[1]=0.9; x2[2]=1.6; x2[3]=1.9; x2[4]=0.5;
x2[5]=0.6; x2[6]=1.1; x2[7]=1.0; x2[8]=0.5;
#endif
int nobs = 9; // number of observations
int npred = 2; // number of predictor values
// we want to find the values of a,a1,a2 to give the best
// fit of y[i] with a0 + a1*x1[i] + a2*x2[i]
// Also print diagonal elements of hat matrix, X*(X.t()*X).i()*X.t()
// this example demonstrates five methods of calculation
Try
{
test1(y, x1, x2, nobs, npred);
test2(y, x1, x2, nobs, npred);
test3(y, x1, x2, nobs, npred);
test4(y, x1, x2, nobs, npred);
test5(y, x1, x2, nobs, npred);
}
CatchAll { cout << BaseException::what(); }
}
#ifdef DO_FREE_CHECK
FreeCheck::Status();
#endif
Real* s2; { ColumnVector A(8000); s2 = A.Store(); }
cout << "\n\nThe following test does not work with all compilers - see documentation\n";
cout << "Checking for lost memory: "
<< (unsigned long)s1 << " " << (unsigned long)s2 << " ";
if (s1 != s2) cout << " - error\n"; else cout << " - ok\n";
return 0;
}
|