sp_densityfnct.cpp

Go 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