Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

models.cpp

00001 #include "models.h"     
00002 
00003 /////////////////////////////////////////////////////////
00004 //  functions belonging to the class MODEL:            //
00005 /////////////////////////////////////////////////////////
00006 
00007 
00008 safevector<double> MODEL::simulatevector(long n) {
00009   safevector<double> res(n);
00010   matrix simdata = simulate(n);
00011   for (long i=0; i<n; i++) 
00012     res[i] = simdata.get(i);
00013   return res;
00014 }
00015 
00016 /////////////////////////////////////////////////////////
00017 //  functions belonging to the class MARKOVMODEL:      //
00018 /////////////////////////////////////////////////////////
00019 
00020 matrix MARKOVMODEL::simulate(long n)  
00021 {
00022   matrix X(n);
00023   long i;
00024   X.set(startvalue,0);
00025   for(i=1;i<=n-1;i++)
00026     X.set(next(X.get(i-1)),i);
00027   return(X);
00028 }
00029 
00030 
00031 ///////////////////////////////////////////////////////
00032 //  functions belonging to the class SVMODEL:  //
00033 ///////////////////////////////////////////////////////
00034 
00035 matrix SVMODEL::simulateS(long n) 
00036 { 
00037   matrix S(n);
00038   matrix v;
00039   double tmp;
00040   long i,j;
00041 
00042   setinitvalue();
00043   
00044   for(i=0;i<=n-1;i++)
00045     {
00046       v = MARKOVMODEL::simulate(PointsPerDelta);
00047       tmp=0.5*(v.get(0)+v.get(PointsPerDelta-1));
00048       for(j=1;j<=PointsPerDelta-1;j++)
00049         {
00050           tmp += v.get(j); 
00051         }
00052       S.set(delta*tmp,i);
00053       MARKOVMODEL::setstartvalue(v.get(PointsPerDelta-1));
00054     }
00055   return(S);
00056 }
00057 
00058 matrix SVMODEL::simulate(long n)
00059 {
00060   matrix S(n);
00061   matrix Y(n);
00062   long i;
00063 
00064   S = simulateS(n);
00065 
00066   for(i=0;i<=n-1;i++)
00067     Y.set(sqrt(S.get(i))*rnorm2(seed),i,0);
00068   return(Y);
00069 }
00070 
00071 ////////////////////////////////////////////////////////////
00072 //  functions belonging to the class PREESTMODEL:         //
00073 ////////////////////////////////////////////////////////////
00074 
00075 
00076 //#############
00077 //############# WE ONLY NEED TO CHANCE THEESE TWO FUNCTIONS IN ORDER TO EXTEND THE PROGRAM TO MORE GENEREAL
00078 //############# CHOICES OF Z_j^i. PREESTMODEL::Zval & PREESTMODEL::calculate_Z
00079 //############# 
00080 //############# The smart way to do this is to create a subclass with theese two functions. 
00081 //############# If for instance you create a new class MYMODEL inheriting from PREESTMODEL, and you have written the appropiate MYMODEL::next function (simulation), then it automatically inherits the canonic choice of Z-functions. If you however to choose to look at other Z-functions, then you just need to create a subclass MODEL1 that inherits from MYMODEL, and then simply reimplent MYMODEL1::Zval and MODEL1::calculate_Z. 
00082 
00083 double PREESTMODEL::Zval(unsigned j, long i, long k, matrix const& Y) { // Z_{jk}^{(i)}, j=0,...,N-1, k=1,...,q, i
00084   double (*fj)(double) = ifuncs[j];
00085   double x = Y.get(i-k);
00086   return fj(x);
00087   //  return fdata[j].get(i-k); // f_j(X_{i+1-k})
00088 }
00089 
00090 void PREESTMODEL::calculate_Z() {
00091  
00092   Z.clear();
00093   fXnext.clear();
00094   fX1.clear();
00095   for (unsigned j=0; j<N; j++) {
00096     double (*fj)(double) = ifuncs[j];
00097     Z.push_back(X.map(fj)); // Should probably be calculated within Zval. Then we only need to chance Zval in the future.
00098     fXnext.push_back(Xnext.map(fj));
00099     fX1.push_back(X1.map(fj));
00100   }
00101 }
00102 
00103 //#############
00104 //############# ^^^^^^^^^^^^^^ READ ABOVE COMMENT
00105 //############# 
00106 //#############
00107 
00108 
00109 void PREESTMODEL::setdata(matrix Y) {
00110   MODEL::setdata(Y); // Setting data
00111   fdata.clear();
00112   for (unsigned j=0; j<N; j++) {
00113     double (*fj)(double) = ifuncs[j];
00114     fdata.push_back(Y.map(fj));
00115   }
00116 }
00117 
00118 void PREESTMODEL::calculate_X() {
00119   //  setseed(-12345);
00120   // Initializing matrices...
00121   X.newsize(numsimul,q);
00122   Xnext.newsize(numsimul);
00123   X1.newsize(numsimul);
00124   
00125   assert(s>=q+1);
00126   long start = s-1;
00127   for (unsigned k=0; k<numsimul; k++) {
00128     matrix Xs = simulate(s+1); // We simulate X_1,...,X_{s+1} each numsimul times.
00129     Xnext.set(Xs.get(s),k); // X_{s+1}
00130     X1.set(Xs.get(0),k);  // X_1
00131     for (long i=0; i<q; i++) { 
00132       X.set(Xs.get(start-i),k,i); // X_s,...,X_{s+1-q}
00133     }
00134   }
00135 }
00136 
00137 void PREESTMODEL::calculate_C() {
00138   C.clear();
00139   for (unsigned j=0; j<N; j++) {
00140     C.push_back(Z[j].covar());
00141   }
00142 }
00143 
00144 void PREESTMODEL::calculate_b()
00145 {
00146   b.clear();
00147   for (unsigned j=0; j<N; j++) {
00148     b.push_back(covar2(Z[j],fXnext[j]));
00149   }
00150 }
00151 
00152 void PREESTMODEL::calculate_a()
00153 {
00154   setseed(-123456); // Fixed seed. Since we need to calculate the derivative of alpha.
00155 
00156   calculate_X();
00157   calculate_Z();
00158   calculate_b();
00159   calculate_C();
00160   
00161   a.clear();
00162   a0.clear();
00163   EtildeZ.clear();
00164   for (unsigned j=0; j<N; j++) {
00165     matrix aj = pseudoinverse(C[j])*b[j];
00166   
00167     double EfX1 = (fX1[j].mean())[0];
00168     safevector<double> EZj = Z[j].mean();
00169     
00170     matrix EtildeZj(q+1); // MS. bottom p.9 
00171     EtildeZj.set(1,0);
00172     for (long kk=1; kk<=q; kk++) {
00173       EtildeZj.set(EZj[kk-1], kk);
00174     }
00175     EtildeZ.push_back(EtildeZj);
00176 
00177     double prod = 0; // Calculating inner-product <a,EZj>
00178     for (int i=0; i<q; i++) {
00179       prod += aj.get(i)*EZj[i];
00180     }
00181     double aj0 = EfX1 - prod;  // a_j0
00182     a.push_back(aj);
00183     a0.push_back(aj0);
00184   }
00185   b.clear();  
00186 }
00187 
00188 
00189 double PREESTMODEL::prediction(unsigned j, long i, matrix const& Y)
00190 {
00191 
00192   assert (j<N);
00193   assert (i>=1 && i<=Y.row());
00194 
00195   double res = a0[j];
00196   for(int k=1; k<=q; k++) {
00197     res -= a[j].get(k-1)*Zval(j,i,k, Y); // <a_j|Z_j^{i-1}>
00198   }
00199   return(res);
00200 }
00201 
00202 
00203 matrix PREESTMODEL::sumH(matrix par)
00204 
00205 {
00206   double res;
00207   matrix sumH(N*(q+1));
00208 
00209   setpar(par);
00210   long n=getdatasize();
00211   
00212   calculate_a();
00213 
00214   for (long i=s+1; i<=n; i++) // sum_{i=s+1}^n H^i
00215     { 
00216       for (unsigned j=0; j<N; j++) {// calculate Z_{j0}, j=1,...,N
00217         double residual = fdata[j].get(i-1)-prediction(j,i-1,getdata()); // f_j(X_i)-pi_j(i-1)
00218         res = Zval(j,i-1,0,getdata())*residual; // Z_{j0}^{(i-1)}
00219         sumH.add(res,j*(q+1)); // Z_{j0} on row j(q+1)
00220         for(long k=1; k<=q; k++) {
00221           res = Zval(j,i-1,k,getdata())*residual;
00222           sumH.add(res,j*(q+1)+k); // Z_{jk}
00223         }
00224       }
00225     }    
00226 
00227   if (printdebug) {
00228     std::cerr << "\n\nsumH=\n";
00229     sumH.stdprint();
00230     std::cerr << "\n";    
00231   }
00232 
00233     
00234   return(sumH);
00235 }
00236 
00237 
00238 //! First term in \f$\overline{M}\f$ : \f$E_\theta(H^{(r)}(\theta)H^{(r+i)}(\theta))\f$. Under the assumption that our incoming process is ergodic, we can approximate this term by calculating the mean.
00239 void PREESTMODEL::calculate_EHH() {
00240 
00241   long m=l;
00242   if(q>l) m=q;
00243   
00244   matrix H(N*(q+1)); // Simulation of H
00245   matrix M(N*(q+1), N*(q+1)); 
00246 
00247   simY=simulate(MbarNOS+1);
00248 
00249   for(long i=m; i<MbarNOS; i++) {
00250     //!   Iteration no. i
00251 
00252     for (unsigned j=0; j<N; j++) {
00253       double (*fj)(double) = ifuncs[j];
00254       for (long k=0; k<=q; k++) {
00255         //! OBS: \breve{\alpha} has already been calculated, so we can use prediction directly without calling calculate_a();
00256         double res = fj(simY.get(i))-prediction(j,i-1,simY);
00257         if (k>0) // Pr. defintion: Z_{j0}^{(i-1)} = 1
00258           res *= Zval(j,i-1,k,simY); 
00259         // index (j,k) is placed in H at location (j-1)*(q+1)+k (We index from 0).
00260         unsigned Hindex = j*(q+1)+k;
00261         H.set(res,Hindex);
00262       }
00263     } // Now we have calculated H^(i)(theta)
00264 
00265 
00266     // Next we calculate the mean*normalization.
00267     for (unsigned r=0; r<N*(q+1); r++) {
00268       for (unsigned s=0; s<N*(q+1); s++) {     
00269         M.add(H.get(r)*H.get(s),r,s); // Here we add (H*H^t)_(rs) = (H)_r*(H)_s to the matrix M.
00270       }
00271     }
00272   }
00273 
00274   double w = (double)1/(double)(MbarNOS - m +1);  
00275   EHH = M*w; 
00276 
00277   qmove(1,25);
00278   varH.newsize(N*(q+1));
00279   
00280   for (unsigned k=0; k<N*(q+1); k++)                                
00281     varH.set(EHH.get(k,k),k);                        // the diagonal of E((H^r)(H^r)^T) is the
00282                                                      // variances of the coordinates of H^r.
00283                                                      // This is the reason why we break the
00284                                                      // calculation of Mbar up into two pieces.
00285 }
00286 
00287 void PREESTMODEL::set_Mbar_terms(double lambda)
00288 {
00289   double K;
00290 
00291   K=varH.maxvalue();
00292 
00293   for(long k=0; k<MbarNOS-q;k++){
00294     if(K/exp(lambda*(k-q))<0.0001){
00295       Mbar_terms=k;
00296       break;}
00297   }
00298 
00299 }
00300 
00301 void PREESTMODEL::calculate_Mbar()
00302 {
00303   int m=l;
00304 
00305   matrix H1(N*(q+1)),H2(N*(q+1)),M(N*(q+1),N*(q+1));
00306   calculate_EHH();
00307   set_Mbar_terms(sumH_est);                         // lambda=theta is set to sumH_est. The estimate
00308                                                     // is based on sumH, and should be found prior to calling estfunc.
00309   Mbar=EHH;
00310 
00311   if(q>l) m=q;
00312 
00313   std::string ss = "Mbar_terms = " + numStr(Mbar_terms);
00314   if (printdebug)
00315     qmvaddstr(30,50, ss.c_str());  qclrtoeol();
00316 
00317   qmove(29,12);
00318   for(long k=1;k<=Mbar_terms;k++){
00319     M=M*0;
00320 
00321     for(long i=m; i<MbarNOS-k; i++) {
00322       
00323       
00324       for (unsigned j=0; j<N; j++) {
00325         double (*fj)(double) = ifuncs[j];
00326         for (long r=0; r<=q; r++) {
00327           // OBS: \breve{\alpha} has already been calculated, so we can use prediction directly without calling calculate_a();
00328           double res1 = fj(simY.get(i))-prediction(j,i-1,simY);
00329           double res2 = fj(simY.get(i+k))-prediction(j,i+k-1,simY);
00330           if (k>0) { // Pr. defintion: Z_{j0}^{(i-1)} = 1 
00331             res1 *= Zval(j,i-1,r,simY); 
00332             res1 *= Zval(j,i+k-1,r,simY); 
00333           }
00334           // index (j,k) is placed in H at location (j-1)*(q+1)+k (We index from 0).
00335           unsigned Hindex = j*(q+1)+r;
00336           H1.set(res1,Hindex);
00337           H2.set(res2,Hindex);
00338         }
00339       } // Now we have calculated H^(i)(theta) and H^(i+r)(theta)
00340           
00341       M = M+(H1*H2.trans());    
00342     }
00343 
00344     M=M+M.trans(); // See MS(3.14).
00345     double w1=(double) 1/(MbarNOS-k-m);                          
00346     double w2=(MbarNOS-q-k);
00347     double w3=(double) 1/(MbarNOS-q);
00348     M=M*w1;
00349     Mbar=Mbar+M*w2*w3; 
00350   }
00351 
00352   qmove(26,1); qclrtoeol();
00353   qmove(27,1); qclrtoeol();
00354   qmove(28,1); qclrtoeol();
00355   qmove(29,1); qclrtoeol();
00356 }
00357 
00358 
00359 
00360 matrix PREESTMODEL::calculate_Cbar() {
00361   matrix Cbar(N*(q+1), N*(q+1));
00362 
00363   for (unsigned j=0; j<N; j++) {
00364     matrix EZ2 = EtildeZ[j]*EtildeZ[j].trans();
00365     double val;
00366     for (long r=0; r<=q; r++) {
00367       for (long s=0; s<=q; s++) {
00368         long super_r = j*(q+1)+r;
00369         long super_s = j*(q+1)+s;
00370         if (r==0 || s==0) {
00371           val = EZ2.get(r,s);
00372         }
00373         else {
00374           val = C[j].get(r-1,s-1) + EZ2.get(r,s);
00375         }
00376         Cbar.set(val,super_r,super_s);
00377          
00378       }
00379     }
00380   }
00381 
00382   return Cbar;
00383 }
00384 
00385 
00386 matrix PREESTMODEL::calculate_Dalpha() { // Estimating derivatives of function alpha
00387   unsigned p = noofpar();
00388   matrix res(N*(q+1),p);
00389   double epsilon = 0.01;
00390   matrix origpar = getpar();
00391 
00392   safevector<matrix> a_orig = a;
00393   safevector<double> a0_orig = a0;
00394 
00395   
00396   for (unsigned i=0; i<p; i++) {
00397     matrix newpar = origpar;
00398     newpar.set(newpar.get(i)+epsilon,i); // used to estimate i'th partial derivative of alpha
00399     setpar(newpar);
00400 
00401     calculate_a();
00402 
00403     for (unsigned j=0; j<N; j++) {  
00404       matrix cur_aj = a[j];
00405       matrix orig_aj = a_orig[j];
00406       double Da0 = (a0[j]-a0_orig[j])/epsilon; // (f(x+e)-f(x))/e ~= f'(x)
00407       res.set(Da0,j*(q+1),i);
00408       for (int k=0; k<q; k++) {
00409         double Daj = (cur_aj.get(k)-orig_aj.get(k))/epsilon;
00410         unsigned rr= (unsigned)j*(q+1)+k+1;
00411         res.set(Daj,rr,i);
00412       }
00413     }
00414   }
00415 
00416   setpar(origpar);
00417   return res;
00418 }
00419 
00420 
00421 
00422 void PREESTMODEL::calculate_Astar() {
00423   if (printdebug)
00424     qmvaddstr(30,50, "Calculating Astar:");    
00425   matrix Cbar = calculate_Cbar();
00426   if (printdebug)
00427     qmvaddstr(30,50, "Calculating Mbar:");  qclrtoeol();  
00428   calculate_Mbar();
00429   if (printdebug)
00430     qmvaddstr(30,50, "Calculating MbarInv (using pseudoinverse):");
00431   matrix MbarInv = pseudoinverse(Mbar);
00432   if (printdebug)
00433     qmvaddstr(30,50, "Calculating Dalpha:"); qclrtoeol();
00434   matrix Dalpha = calculate_Dalpha();
00435 
00436   matrix U = Cbar*Dalpha;
00437   Astar = U.trans()*MbarInv;
00438   if (printdebug)
00439     qmvaddstr(30,50, ""); qclrtoeol();
00440 
00441   if (printdebug) {
00442     std::cerr << "\nMbarInv=\n";
00443     MbarInv.stdprint();
00444     std::cerr << "\nU=\n";
00445     U.stdprint();
00446     std::cerr << "\nDalpha=\n";
00447     Dalpha.stdprint();
00448 
00449   //   std::cerr << "Dalpha.trans = " << Dalpha.row() << "x" << Dalpha.column() << std::endl;
00450   //   std::cerr << "dim(Cbar) = " << Cbar.row() << "x" << Cbar.column()<< std::endl;
00451   //   std::cerr << "dim(MbarInv) = " << MbarInv.row() << "x" << MbarInv.column()<< std::endl;
00452   //   std::cerr << "Dalpha=\n";
00453   //   Dalpha.stdprint();
00454     std::cerr << std::endl << std::endl;
00455   }
00456 
00457 }
00458 
00459 
00460 matrix PREESTMODEL::estfunc(matrix par)
00461 {
00462   matrix sumHH=sumH(par);
00463   setpar(par);  // Pre-estimate
00464 
00465   // We only calculate Astar (and hence Mbar) if iter_Mbar is set.
00466   if (iter_Mbar) {
00467     calculate_Astar();
00468   }
00469   return Astar*sumHH;
00470 }
00471 
00472 
00473 
00474 /////////////////////////////////////////////////////
00475 //  functions belonging to the class SVCIR:        //
00476 /////////////////////////////////////////////////////
00477 
00478 
00479 void SVCIR::setpar(matrix par) {
00480   alpha=par.get(0); theta=par.get(1); sigma=par.get(2); MODEL::setpar(par);
00481 }
00482 
00483 unsigned SVCIR::getdim() { return(3); }
00484 
00485 double SVCIR::next(double oldvalue) const
00486 { 
00487   double newvalue;
00488   double deltaW;
00489 
00490   deltaW=sqrt(delta)*rnorm2(seed);
00491   newvalue = oldvalue - theta*(oldvalue-alpha)*delta+ 
00492     sigma*sqrt(oldvalue)*deltaW + 
00493     ((double) sigma*sigma/4)*(deltaW*deltaW-delta);
00494   return(newvalue);
00495 }
00496 
00497 /////////////////////////////////////////////////////
00498 //  functions belonging to the class SVEOU:        //
00499 /////////////////////////////////////////////////////
00500 
00501 void SVEOU::setpar(matrix par) {
00502   alpha=par.get(0); theta=par.get(1); sigma=par.get(2); MODEL::setpar(par);
00503 } 
00504 
00505 unsigned SVEOU::getdim() { return(3); }
00506 
00507 double SVEOU::next(double oldvalue) const
00508 {
00509   double newvalue;
00510   double DeltaW;
00511   
00512   DeltaW =  sqrt(sigma*sigma/(2*theta)*(1-exp(-2*theta*delta)))*rnorm2(seed);
00513   newvalue = exp(alpha*(1-exp(-theta*delta)) + exp(-theta*delta)*log(oldvalue) + DeltaW);
00514 
00515   return(newvalue);
00516 }
00517 
00518 
00519 /////////////////////////////////////////////////////
00520 //  functions belonging to the class SVEOU1:        //
00521 /////////////////////////////////////////////////////
00522 
00523 
00524 double SVEOU1::Zval(unsigned j, long i, long k, matrix const& Y) { // Z_{jk}^{(i)}, j=0,...,N-1, k=1,...,q, i
00525   double (*fj)(double) = ifuncs[j];
00526   double x = Y.get(i-k);
00527   return sqrt(fj(x));
00528 }
00529 
00530 void SVEOU1::calculate_Z() {
00531  
00532   Z.clear();
00533   fXnext.clear();
00534   fX1.clear();
00535   for (unsigned j=0; j<N; j++) {
00536     double (*fj)(double) = ifuncs[j];
00537     Z.push_back(X.map(fj)); // Should probably be calculated within Zval. Then we only need to chance Zval in the future.
00538     fXnext.push_back(Xnext.map(fj));
00539     fX1.push_back(X1.map(fj));
00540   }
00541 }
00542 
00543 ////////////////////////////////////////////////////////////////////////////////
00544 
00545 
00546 #ifdef TEST
00547 
00548 int main() {
00549   try {
00550     std::cerr << "Nothing to test in models.cpp\n";
00551   } catch(std::string const& err) {
00552     std::cerr << err << std::endl;
00553     return 1;
00554   }
00555   return 0;
00556 }
00557 
00558 
00559 #endif//TEST

Generated on Tue Feb 14 16:05:52 2006 for estfunc by doxygen 1.3.6