sp_densityfnct.cppGo to the documentation of this file.00001 /** @file sp_densityfnct.cpp Discrete density function approximation */ 00002 00003 00004 /* 00005 Copyright (C) 2008 Thomas Moor 00006 Exclusive copyright is granted to Klaus Schmidt 00007 */ 00008 00009 #include "sp_densityfnct.h" 00010 #include "sp_executor.h" 00011 00012 #include <cmath> 00013 00014 namespace faudes { 00015 00016 /* 00017 *********************************************************** 00018 *********************************************************** 00019 *********************************************************** 00020 00021 implementation of density function approximattion 00022 00023 *********************************************************** 00024 *********************************************************** 00025 *********************************************************** 00026 */ 00027 00028 // construct 00029 DiscreteDensityFunction::DiscreteDensityFunction(void) : 00030 mCount(0), mMaxValue(0), mMinValue(0), mMaxTime(0), mMinTime(0), mSum(0), mSquareSum(0), mAverage(0), mVariance(0), mQuantile05(0), mQuantile95(0) 00031 { 00032 } 00033 00034 //Write(rTw); 00035 void DiscreteDensityFunction::Write(TokenWriter& rTw) const { 00036 Token token; 00037 rTw.WriteBegin("Density"); 00038 rTw << Name(); 00039 int oldcolumns = rTw.Columns(); 00040 rTw.Columns(3); 00041 rTw << "\n"; 00042 for(CIterator mit=Begin(); mit!=End(); mit++) { 00043 if(mit->second.value==0) continue; 00044 rTw.WriteFloat(mit->second.timeint.LB()); 00045 rTw.WriteFloat(mit->second.timeint.UB()); 00046 rTw.WriteFloat(mit->second.value); 00047 } 00048 rTw.Columns(oldcolumns); 00049 rTw.WriteEnd("Density"); 00050 } 00051 00052 // ToString() 00053 std::string DiscreteDensityFunction::ToString(void) const { 00054 TokenWriter tw(TokenWriter::String); 00055 Write(tw); 00056 return tw.Str(); 00057 } 00058 00059 // Write() 00060 void DiscreteDensityFunction::Write(void) const { 00061 TokenWriter tw(TokenWriter::Stdout); 00062 Write(tw); 00063 } 00064 00065 //Read(rTr) 00066 void DiscreteDensityFunction::Read(TokenReader& rTr) { 00067 Clear(); 00068 rTr.ReadBegin("Density"); 00069 rTr.ReadEnd("Density"); 00070 } 00071 00072 00073 // reset all 00074 void DiscreteDensityFunction::Clear(void) { 00075 FD_DX("DiscreteDensityFunction::Clear()"); 00076 mValueMap.clear(); 00077 mMinValue=0; 00078 mMaxValue=0; 00079 mMinTime=0; 00080 mMaxTime=0; 00081 mSum=0; 00082 mSquareSum=0; 00083 mAverage=0; 00084 mVariance=0; 00085 mQuantile05=0; 00086 mQuantile95=0; 00087 mCount=0; 00088 } 00089 00090 // const fake version 00091 void DiscreteDensityFunction::Compile(void) const { 00092 DiscreteDensityFunction* fakeconst = const_cast<DiscreteDensityFunction*>(this); 00093 fakeconst->CompileNonConst(); 00094 } 00095 00096 // compute (assume right open intervals) 00097 void DiscreteDensityFunction::CompileNonConst(void) { 00098 FD_DX("DiskreteDensityFunction::Compile(" << mName << ")"); 00099 if(mValueMap.size()<1) return; // error 00100 // normalize 00101 double integral=0; 00102 for(Iterator mit=Begin() ;mit!=End(); mit++) { 00103 integral+= (mit->second.timeint.UB()-mit->second.timeint.LB())* mit->second.value; 00104 }; 00105 if(integral==0) return; // error 00106 double norm=1/integral; 00107 for(Iterator mit=Begin() ;mit!=End(); mit++) { 00108 mit->second.value*= norm; 00109 }; 00110 // find min, max, and sums 00111 mMinValue=-1; 00112 mMaxValue=-1; 00113 mMinTime=-1; 00114 mMaxTime=-1; 00115 mSum=0; 00116 mSquareSum=0; 00117 for(Iterator mit=Begin() ;mit!=End(); mit++) { 00118 if(mMinValue<0 || (mit->second.value < mMinValue)) mMinValue=mit->second.value; 00119 if(mMaxValue<0 || (mit->second.value > mMaxValue)) mMaxValue=mit->second.value; 00120 double time = (mit->second.timeint.UB() -1 + mit->second.timeint.LB()) / 2.0; // discrete time 00121 double prob = (mit->second.timeint.UB() - mit->second.timeint.LB()) * mit->second.value; 00122 mSum=mSum + time * prob; 00123 mSquareSum=mSquareSum + time*time*prob; 00124 } 00125 // min and max 00126 if(mMinValue<0) mMinValue=0; 00127 if(mMaxValue<0) mMaxValue=0; 00128 mMinTime=Begin()->second.timeint.LB(); 00129 mMaxTime=(--End())->second.timeint.UB() -1; // discrete time; 00130 // avaerage and variance 00131 mAverage= mSum; 00132 mVariance=sqrt(fabs(mSquareSum - mSum*mSum)); // fix!! 00133 // quantile 05 (todo: inspect/test/fix) 00134 mQuantile05=mMinTime; 00135 integral=0; 00136 double len=0, area=0; 00137 Iterator mit; 00138 for(mit=Begin() ;mit!=End(); mit++) { 00139 len = mit->second.timeint.UB()-mit->second.timeint.LB(); 00140 area=len* mit->second.value; 00141 if(integral + area >= 0.05) break; 00142 integral = integral + area; 00143 } 00144 if((mit!=End()) && (integral + area >= 0.05)) { 00145 if(mit->second.value>0.01) 00146 mQuantile05 = mit->second.timeint.LB() + (0.05-integral)/mit->second.value; 00147 else 00148 mQuantile05 = mit->second.timeint.LB() + len/2; 00149 } 00150 if(mQuantile05<=mMinTime) mQuantile05=mMinTime; 00151 // quantile 95 (todo: inspect/test/fix) 00152 mQuantile95=mMaxTime; 00153 integral=0; 00154 len=0, area=0; 00155 for(mit=End();mit!=Begin(); ) { 00156 mit--; 00157 len = mit->second.timeint.UB()-mit->second.timeint.LB(); 00158 area=len* mit->second.value; 00159 if(integral + area >= 0.05) break; 00160 integral = integral + area; 00161 } 00162 if(integral +area >= 0.05) { 00163 if(mit->second.value>0.01) 00164 mQuantile95 = mit->second.timeint.UB() - (0.05-integral)/mit->second.value; 00165 else 00166 mQuantile95 = mit->second.timeint.UB() - len/2; 00167 } 00168 if(mQuantile95>=mMaxTime) mQuantile95=mMaxTime; 00169 } 00170 00171 00172 // get entry, perhaps fake 00173 const DiscreteDensityFunction::Entry DiscreteDensityFunction::EntryAt(tpTime::Type time) const { 00174 CIterator mit= At(time); 00175 if(mit!=End()) return mit->second; 00176 Entry dent; 00177 dent.timeint.SetPositive(); 00178 dent.value = 0; 00179 return dent; 00180 } 00181 00182 00183 // get value 00184 double DiscreteDensityFunction::Value(tpTime::Type time) const { return EntryAt(time).value; } 00185 const TimeInterval& DiscreteDensityFunction::TimeInt(tpTime::Type time) const { return EntryAt(time).timeint; } 00186 00187 // pretty string (should resample) 00188 std::string DiscreteDensityFunction::Str(void) const { 00189 std::stringstream ss; 00190 ss << "% Discrete Density \"" << mName <<"\"" << " characteristics:" << std::endl; 00191 ss << "% time " << MinTime() << "/" << MaxTime() << std::endl; 00192 ss << "% value " << MinValue() << "/" << MaxValue() << std::endl; 00193 ss << "% quant " << Quantile05() << "/" << Quantile95() << std::endl; 00194 ss << "% stat " << Average() << "/" << Variance() << std::endl; 00195 for(CIterator mit=Begin(); mit!=End(); mit++) { 00196 if(mit->second.value==0) continue; 00197 ss << "% " << ExpandString(mit->second.timeint.Str(),FD_NAMELEN) << ": " 00198 << ExpandString(ToStringFloat(mit->second.value), FD_NAMELEN) << ": "; 00199 double pc=mit->second.value; 00200 double sc= MaxValue()/50.0; 00201 for(; pc>0; pc-=sc) ss << "#"; 00202 ss << " " << std::endl; 00203 } 00204 return ss.str(); 00205 } 00206 00207 00208 /* 00209 *********************************************************** 00210 *********************************************************** 00211 *********************************************************** 00212 00213 implementation of sampled density function approximattion 00214 00215 *********************************************************** 00216 *********************************************************** 00217 *********************************************************** 00218 */ 00219 00220 00221 00222 // construct 00223 SampledDensityFunction::SampledDensityFunction(void) : DiscreteDensityFunction(), 00224 mDim(100), mCountSum(0), mCountSquareSum(0) 00225 { 00226 } 00227 00228 00229 00230 // clear all 00231 void SampledDensityFunction::Clear(void) { 00232 FD_DX("SampledDensityFunction::Clear()"); 00233 DiscreteDensityFunction::Clear(); 00234 mCount=0; 00235 mCountSum=0; 00236 mCountSquareSum=0; 00237 mCountMap.clear(); 00238 } 00239 00240 // add one sample 00241 void SampledDensityFunction::Sample(tpTime::Type duration) { 00242 // report 00243 FD_DX("SampledDensityFunction::Sample(" << Name() << "): duration " << duration); 00244 FD_DX(SStr()); 00245 // bail out on negative duration (error) 00246 if(duration<0) return; 00247 // record 00248 mCount++; 00249 mCountSum+=duration; 00250 mCountSquareSum+=duration*duration; 00251 // cases ... 00252 CountIterator mit = mCountMap.lower_bound(duration); 00253 // ... do we have a range? just count 00254 if(mit!=mCountMap.end()) { 00255 if(mit->second.timeint.In(duration)) { 00256 FD_DX("SampledDensityFunction::Sample(): range found, count"); 00257 mit->second.count+=1; 00258 return; 00259 } 00260 } 00261 // insert tailord support 00262 FD_DX("SampledDensityFunction::Sample(): insert tailored support"); 00263 CountEntry tent; 00264 tent.timeint.UB(duration); 00265 tent.timeint.LB(duration); 00266 tent.timeint.UBincl(true); 00267 tent.timeint.LBincl(true); 00268 tent.count=1; 00269 mCountMap[duration]=tent; 00270 // dim ok? done 00271 if(mCountMap.size()<=mDim) 00272 return; 00273 // merge intervals 00274 FD_DX("SampledDensityFunction::Sample(): merge"); 00275 CountIterator mit1=mCountMap.begin(); 00276 CountIterator mit2=mCountMap.begin(); 00277 CountIterator mmit; 00278 double minarea = -1; 00279 for(mit2++; mit2!=mCountMap.end(); mit1++, mit2++) { 00280 tpTime::Type dur = mit2->second.timeint.UB() - mit1->second.timeint.LB(); 00281 double area = dur * (mit2->second.count + mit1->second.count); 00282 if(area < minarea || minarea <0) { minarea=area; mmit=mit1;} 00283 } 00284 if(mit2==mCountMap.end()) return; // error! 00285 // merge intervals 00286 mit2=mmit; 00287 mit2++; 00288 mmit->second.timeint.Merge(mit2->second.timeint); 00289 mmit->second.count += mit2->second.count; 00290 mCountMap.erase(mit2); 00291 } 00292 00293 00294 // compute (incl normalize) 00295 void SampledDensityFunction::CompileNonConst(void) { 00296 FD_DX("SampledDensityFunction::Compile(" << mName << ")"); 00297 FD_DX(SStr()); 00298 if(mCountMap.size()<1) return; // error 00299 00300 // convert count 00301 double count=mCount; 00302 00303 // clear main data 00304 mValueMap.clear(); 00305 00306 // copy 00307 if(count<=0) return; // error 00308 for(CountIterator mit=mCountMap.begin() ;mit!=mCountMap.end(); mit++) { 00309 Entry tent; 00310 tent.timeint = mit->second.timeint; 00311 tent.value = ((double) mit->second.count); 00312 mValueMap[tent.timeint.LB()]=tent; 00313 } 00314 00315 // fix bounds: insert (assume all closed) 00316 if(mCountMap.size()<mDim/2) 00317 for(Iterator mit=Begin() ;mit!=End(); mit++) { 00318 Iterator nit=mit; 00319 nit++; 00320 if(nit!=End()) 00321 if(mit->second.timeint.UB() + 1 != nit->second.timeint.LB()) { // todo: float time 00322 Entry tent; 00323 tent.timeint.LB(mit->second.timeint.UB() + 1); 00324 tent.timeint.UB(nit->second.timeint.LB() - 1); 00325 tent.timeint.LBincl(false); 00326 tent.timeint.UBincl(false); 00327 tent.value = 0; 00328 mValueMap[tent.timeint.LB()]=tent; 00329 } 00330 } 00331 00332 // fix bounds: extend over gaps (assume all closed, turn to right open) 00333 for(Iterator mit=Begin() ;mit!=End(); mit++) { 00334 Iterator nit=mit; 00335 nit++; 00336 mit->second.timeint.UBincl(false); 00337 mit->second.timeint.LBincl(true); 00338 mit->second.timeint.UB(mit->second.timeint.UB()+1); 00339 if(nit!=End()) 00340 if(mit->second.timeint.UB() != nit->second.timeint.LB()) { 00341 double middle = 0.5*(mit->second.timeint.UB() + nit->second.timeint.LB()); 00342 tpTime::Type dmiddle=((tpTime::Type) middle); 00343 if(dmiddle <= mit->second.timeint.LB()) dmiddle= nit->second.timeint.LB(); 00344 mit->second.timeint.UB(dmiddle); 00345 nit->second.timeint.LB(dmiddle); 00346 } 00347 if(nit==End()) 00348 if(mit->second.timeint.UB() <= mit->second.timeint.LB()) 00349 mit->second.timeint.UB(mit->second.timeint.LB()+1); 00350 00351 mit->second.value=mit->second.value / 00352 (mit->second.timeint.UB() - mit->second.timeint.LB()); 00353 } 00354 00355 // compile base 00356 DiscreteDensityFunction::CompileNonConst(); 00357 00358 // fix characteristics 00359 mAverage=mCountSum/count; 00360 mVariance=sqrt(1.0/ count * fabs( 00361 mCountSquareSum - (1.0/count*((double)mCountSum)*((double)mCountSum))) ); 00362 00363 FD_DX(DiscreteDensityFunction::Str()); 00364 } 00365 00366 00367 00368 // pretty string 00369 std::string SampledDensityFunction::SStr(void) const { 00370 std::stringstream ss; 00371 ss << "Sampled Density \"" << mName <<"\""; 00372 for(CCountIterator mit=mCountMap.begin(); mit!=mCountMap.end(); mit++) { 00373 ss << "(-- " << mit->second.timeint.Str() << " " << mit->second.count << " --)"; 00374 } 00375 return ss.str(); 00376 } 00377 00378 00379 } // namespace faudes 00380 libFAUDES 2.23h --- 2014.04.03 --- c++ api documentaion by doxygen |