Alex Bikfalvi
SimStream Documentation
Prob.cpp
00001 #include "Headers.h" 00002 #include "Prob.h" 00003 #include "Gamma.h" 00004 00005 #define INTEGRAL_PRECISION 1 00006 00007 CProb::CProb( 00008 double alpha, 00009 double xmin, 00010 double xmax, 00011 const char* cacheFile 00012 ) 00013 { 00014 this->alpha = alpha; 00015 this->xmin = xmin; 00016 this->xmax = xmax; 00017 00018 this->hyp = new Hyp2F1(1, 2-2*this->alpha, 2-this->alpha); 00019 00020 this->c1 = Gamma(1-this->alpha) / Gamma(2-this->alpha); 00021 this->c2 = ((1-this->alpha)*(1-this->alpha)/pow((pow(this->xmax,1-this->alpha)-pow(this->xmin,1-this->alpha)), 2)); 00022 this->c3 = (1-this->alpha)*(1-this->alpha)/(pow(this->xmax,1-this->alpha)-pow(this->xmin,1-this->alpha)); 00023 this->c4 = pow(this->xmax,1-this->alpha); 00024 00025 // Populate cache from the cache file 00026 ifstream file; 00027 try 00028 { 00029 file.open(cacheFile, ios_base::in | ios_base::binary); 00030 00031 cout << "\n[i] Reading abandon probability for the cache file \'" << cacheFile << "\'..." << endl; 00032 00033 file.read((char*)&this->cacheEpiMax, sizeof(this->cacheEpiMax)); 00034 file.read((char*)&this->cacheEciMax, sizeof(this->cacheEciMax)); 00035 file.read((char*)&this->cacheAlpha, sizeof(this->cacheAlpha)); 00036 file.read((char*)&this->cacheXmin, sizeof(this->cacheXmin)); 00037 file.read((char*)&this->cacheXmax, sizeof(this->cacheXmax)); 00038 file.read((char*)&this->cacheEpMin, sizeof(this->cacheEpMin)); 00039 file.read((char*)&this->cacheEpMax, sizeof(this->cacheEpMax)); 00040 file.read((char*)&this->cacheEpDelta, sizeof(this->cacheEpDelta)); 00041 file.read((char*)&this->cacheEcMin, sizeof(this->cacheEcMin)); 00042 file.read((char*)&this->cacheEcMax, sizeof(this->cacheEcMax)); 00043 file.read((char*)&this->cacheEcDelta, sizeof(this->cacheEcDelta)); 00044 00045 cout << "[i] Cache file parameters are: alpha=" << this->cacheAlpha << " xmin=" << this->cacheXmin << " xmax=" << this->cacheXmax << 00046 " ep_min=" << this->cacheEpMin << " ep_max=" << this->cacheEpMax << " ep_delta=" << this->cacheEpDelta << 00047 " ec_min=" << this->cacheEcMin << " ec_max=" << this->cacheEcMax << " ec_delta=" << this->cacheEcDelta << endl; 00048 00049 // Check the cache file 00050 if((this->cacheAlpha == this->alpha) && (this->cacheXmin == this->xmin) && (this->cacheXmax == this->xmax)) 00051 { 00052 // Allocate the cache space 00053 this->cache = new double[this->cacheEciMax*this->cacheEpiMax]; 00054 00055 cout << "[i] Cache file okay. Reading cache data..."; 00056 cout.flush(); 00057 00058 file.read((char*)this->cache, sizeof(double)*this->cacheEpiMax*this->cacheEciMax); 00059 00060 cout << "done." << endl; 00061 } 00062 else 00063 { 00064 cout << "[!] Cache file mismatch (alpha=" << this->alpha << " xmin=" << xmin << " xmax=" << xmax << ")." << endl; 00065 this->CacheDefault(); 00066 } 00067 00068 file.close(); 00069 } 00070 catch(...) 00071 { 00072 cout << "\n[!] Reading abandon probability from the cache file \'" << cacheFile << "\' failed." << endl; 00073 this->CacheDefault(); 00074 } 00075 00076 assert(this->cache); 00077 } 00078 00079 CProb::~CProb() 00080 { 00081 delete this->hyp; 00082 delete[] this->cache; 00083 } 00084 00085 void CProb::CacheDefault() 00086 { 00087 this->cacheAlpha = this->alpha; 00088 this->cacheXmin = cacheXmin; 00089 this->cacheXmax = cacheXmax; 00090 this->cacheEpMin = 0.0; 00091 this->cacheEpMax = this->xmax; 00092 this->cacheEpDelta = 1.0; 00093 this->cacheEcMin = 0.0; 00094 this->cacheEcMax = this->xmax; 00095 this->cacheEcDelta = 1.0; 00096 00097 // Calculate the cache size 00098 this->cacheEpiMax = (unsigned int)((this->cacheEpMax - this->cacheEpMin) / this->cacheEpDelta) + 1; 00099 this->cacheEciMax = (unsigned int)((this->cacheEcMax - this->cacheEcMin) / this->cacheEcDelta) + 1; 00100 00101 // Allocate the cache 00102 this->cache = new double[this->cacheEciMax*this->cacheEpiMax]; 00103 00104 // Set all cache values to default values 00105 for(unsigned int index = 0; index < this->cacheEciMax*this->cacheEpiMax; index++) 00106 this->cache[index] = -1.0; 00107 00108 cout << "[i] Creating default probability cache with parameters: alpha=" << this->cacheAlpha << " xmin=" << this->cacheXmin << " xmax=" << this->cacheXmax << 00109 " ep_min=" << this->cacheEpMin << " ep_max=" << this->cacheEpMax << " ep_delta=" << this->cacheEpDelta << 00110 " ec_min=" << this->cacheEcMin << " ec_max=" << this->cacheEcMax << " ec_delta=" << this->cacheEcDelta << endl; 00111 } 00112 00113 double CProb::Prob(double ep, double ec) 00114 { 00115 // Calculate the cache index (do not go outside of cache boundary) 00116 if(ep > this->cacheEpMax) ep = this->cacheEpMax; 00117 if(ec > this->cacheEcMax) ec = this->cacheEcMax; 00118 00119 if(ep < this->cacheEpMin) ep = this->cacheEpMin; 00120 if(ec < this->cacheEcMin) ec = this->cacheEcMin; 00121 00122 unsigned int epi = (unsigned int)((ep - this->cacheEpMin)/this->cacheEpDelta); 00123 unsigned int eci = (unsigned int)((ec - this->cacheEcMin)/this->cacheEcDelta); 00124 00125 assert(epi < this->cacheEpiMax); 00126 assert(eci < this->cacheEciMax); 00127 00128 unsigned int cindex = eci * this->cacheEpiMax + epi; 00129 00130 /* 00131 * Part I. If value is in the probability in the cache, return the cached value 00132 */ 00133 if(this->cache[cindex] >= 0) return this->cache[cindex]; 00134 00135 /* 00136 * Part II. Else, calculate new value and insert it in the probability cache 00137 */ 00138 this->mutex.Lock(); 00139 this->cache[cindex] = this->InvCdf0(epi, eci); 00140 this->mutex.Unlock(); 00141 00142 return this->cache[cindex]; 00143 } 00144 00145 double CProb::InvCdf0(double ep, double ec) 00146 { 00147 double f = 0; 00148 double z; 00149 00150 if(ec < this->xmin) 00151 if(ep < this->xmin) 00152 { 00153 // ep < this->xmin, ec < this->xmin 00154 z = (0 > this->xmin-this->xmax+ec-ep)?0:this->xmin-this->xmax+ec-ep; 00155 for(; z < ec-ep; z += INTEGRAL_PRECISION) 00156 f += fabs(this->Integral(this->xmax-ec,z,ep,ec) - this->Integral(this->xmin-ep-z,z,ep,ec)) * this->c2; 00157 for(; z <= this->xmax-this->xmin+ec-ep; z += INTEGRAL_PRECISION) 00158 f += fabs(this->Integral(this->xmax-ep-z,z,ep,ec) - this->Integral(this->xmin-ec,z,ep,ec)) * this->c2; 00159 } 00160 else 00161 { 00162 double c = this->c3 / (this->c4-pow(ep,1-this->alpha)); 00163 00164 // ep >= this->xmin, ec < this->xmin 00165 z = (0 > ec-this->xmax)?0:ec-this->xmax; 00166 for(; z < ec-ep; z += INTEGRAL_PRECISION) 00167 f += fabs(this->Integral(this->xmax-ec,z,ep,ec) - this->Integral(-z,z,ep,ec)) * c; 00168 for(; z < ec-this->xmin; z += INTEGRAL_PRECISION) 00169 f += fabs(this->Integral(this->xmax-ep-z,z,ep,ec) - this->Integral(-z,z,ep,ec)) * c; 00170 for(; z < this->xmax-this->xmin+ec-ep; z += INTEGRAL_PRECISION) 00171 f += fabs(this->Integral(this->xmax-ep-z,z,ep,ec) - this->Integral(this->xmin-ec,z,ep,ec)) * c; 00172 } 00173 else 00174 if(ep < this->xmin) 00175 { 00176 double c = this->c3 / (this->c4-pow(ec,1-this->alpha)); 00177 00178 // ep < this->xmin, ec >= this->xmin 00179 z = (0 > this->xmin-this->xmax+ec-ep)?0:this->xmin-this->xmax+ec-ep; 00180 for(; z < this->xmin-ep; z += INTEGRAL_PRECISION) 00181 f += fabs(this->Integral(this->xmax-ec,z,ep,ec) - this->Integral(this->xmin-ep-z,z,ep,ec)) * c; 00182 for(; z < ec-ep; z += INTEGRAL_PRECISION) 00183 f += fabs(this->Integral(this->xmax-ec,z,ep,ec) - this->Integral(0,z,ep,ec)) * c; 00184 for(; z < this->xmax-ep; z += INTEGRAL_PRECISION) 00185 f += fabs(this->Integral(this->xmax-ep-z,z,ep,ec) - this->Integral(0,z,ep,ec)) * c; 00186 } 00187 else 00188 if(ep < ec) 00189 { 00190 double c = (1-this->alpha)*(1-this->alpha)/((this->c4-pow(ep,1-this->alpha))*(this->c4-pow(ec,1-this->alpha))); 00191 00192 // ep >= this->xmin, ec >= this->xmin, ep < ec 00193 z = 0; 00194 for(; z < ec-ep; z += INTEGRAL_PRECISION) 00195 f += fabs(this->Integral(this->xmax-ec,z,ep,ec) - this->Integral(0,z,ep,ec)) * c; 00196 for(; z < this->xmax-ep; z += INTEGRAL_PRECISION) 00197 f += fabs(this->Integral(this->xmax-ep-z,z,ep,ec) - this->Integral(0,z,ep,ec)) * c; 00198 } 00199 else 00200 { 00201 double c = (1-this->alpha)*(1-this->alpha)/((this->c4-pow(ep,1-this->alpha))*(this->c4-pow(ec,1-this->alpha))); 00202 00203 // ep >= this->xmin, ec >= this->xmin, ep >= ec 00204 z = (0 > ec-this->xmax)?0:ec-this->xmax; 00205 for(; z < ec-ep; z += INTEGRAL_PRECISION) 00206 f += fabs(this->Integral(this->xmax-ec,z,ep,ec) - this->Integral(-z,z,ep,ec)) * c; 00207 for(; z < 0; z += INTEGRAL_PRECISION) 00208 f += fabs(this->Integral(this->xmax-ep-z,z,ep,ec) - this->Integral(-z,z,ep,ec)) * c; 00209 for(; z < this->xmax-ep; z += INTEGRAL_PRECISION) 00210 f += fabs(this->Integral(this->xmax-ep-z,z,ep,ec) - this->Integral(0,z,ep,ec)) * c; 00211 } 00212 return f; 00213 } 00214 00215 double CProb::Integral(double x, double z, double ep, double ec) 00216 { 00217 double b = z + ep; 00218 double c = ec; 00219 00220 if(b != c) return this->c1 * pow((x+b)*(x+c), 1-this->alpha) * fabs((*hyp)(-(x+c)/(b-c))) / (b-c); 00221 else return pow(x+b,1-2*this->alpha)/(1-2*this->alpha); 00222 } 00223
Last updated: February 8, 2011