00001 #include "ECF_base.h"
00002 #include "ECF_macro.h"
00003 #include <cmath>
00004
00005
00006 StatCalc::StatCalc()
00007 {
00008 statNo = 0;
00009 statsFileName_ = "";
00010 }
00011
00012
00013 void StatCalc::registerParameters(StateP state)
00014 {
00015 state->getRegistry()->registerEntry("stats.file", (voidP) (new std::string("")), ECF::STRING);
00016 }
00017
00018
00019 bool StatCalc::initialize(StateP state)
00020 {
00021 state_ = state;
00022 average_.clear();
00023 stdDev_.clear();
00024 max_.clear();
00025 min_.clear();
00026 time_.clear();
00027 sampleSize_.clear();
00028 evaluations_.clear();
00029 nEvaluations_ = 0;
00030
00031 if(state->getRegistry()->isModified("stats.file")) {
00032 voidP sptr = state->getRegistry()->getEntry("stats.file");
00033 statsFileName_ = *((std::string*) sptr.get());
00034
00035 statsFile_.open(statsFileName_.c_str());
00036 if(!statsFile_) {
00037 throw std::string("Error: can't open stats file (") + statsFileName_ + ")";
00038 }
00039 }
00040 return true;
00041 }
00042
00043
00047 double StatCalc::getFitnessMin(int generation)
00048 {
00049 if(generation == -1)
00050 generation = statNo;
00051 return min_[generation];
00052 }
00053
00054
00058 double StatCalc::getFitnessMax(int generation)
00059 {
00060 if(generation == -1)
00061 generation = statNo;
00062 return max_[generation];
00063 }
00064
00065
00069 bool StatCalc::operate(const std::vector<IndividualP>& pool)
00070 {
00071 std::vector<double> fitnessTemp;
00072
00073 sampleSize_.push_back((uint)pool.size());
00074 fitnessTemp.resize(pool.size());
00075
00076 for(uint i = 0; i < pool.size(); i++)
00077 fitnessTemp[i] = pool[i]->fitness->getValue();
00078
00079 max_.push_back(fitnessTemp[0]);
00080 min_.push_back(fitnessTemp[0]);
00081 statNo = (uint) max_.size() - 1;
00082 double sum = 0;
00083
00084 for(uint i = 0; i < fitnessTemp.size(); i++) {
00085 if(fitnessTemp[i] > max_[statNo]) {
00086 max_[statNo] = fitnessTemp[i];
00087 }
00088 if(fitnessTemp[i] < min_[statNo]) {
00089 min_[statNo] = fitnessTemp[i];
00090 }
00091 sum += fitnessTemp[i];
00092 }
00093
00094 average_.push_back(sum / fitnessTemp.size());
00095
00096 if(fitnessTemp.size() > 1) {
00097 double numerator = 0, denominator;
00098 for(uint i = 0; i < fitnessTemp.size(); i++) {
00099 numerator += ((fitnessTemp[i] - average_[statNo]) * (fitnessTemp[i] - average_[statNo]));
00100 }
00101 denominator = (fitnessTemp.size() - 1);
00102 stdDev_.push_back(sqrt(numerator / denominator));
00103 }
00104 else
00105 stdDev_.push_back(fitnessTemp[0]);
00106
00107 time_.push_back(state_->getElapsedTime());
00108
00109 evaluations_.push_back(nEvaluations_);
00110
00111 return true;
00112 }
00113
00114
00118 void StatCalc::copyStats(StatCalcP stats)
00119 {
00120 std::vector<double> exStats = stats->getStats();
00121 min_.push_back(exStats[0]);
00122 max_.push_back(exStats[1]);
00123 average_.push_back(exStats[2]);
00124 stdDev_.push_back(exStats[3]);
00125 sampleSize_.push_back((uint) exStats[4]);
00126 time_.push_back((uint) exStats[5]);
00127 evaluations_.push_back((uint) exStats[6]);
00128
00129 nEvaluations_ = evaluations_.back();
00130 statNo = (uint) max_.size() - 1;
00131 }
00132
00133
00137 bool StatCalc::update(std::vector<double> stats)
00138 {
00139 double outMin = stats[0];
00140 double outMax = stats[1];
00141 double outAvg = stats[2];
00142 double outDev = stats[3];
00143 uint outSize = (uint) stats[4];
00144 uint outEval = (uint) stats[6];
00145
00146 if(outMin < min_.back())
00147 min_.back() = outMin;
00148
00149 if(outMax > max_.back())
00150 max_.back() = outMax;
00151
00152 evaluations_.back() += outEval;
00153 nEvaluations_ = evaluations_.back();
00154
00155 uint mySize = sampleSize_.back();
00156 if(mySize > 1) {
00157 sampleSize_.back() = mySize + outSize;
00158 double myAvg = average_.back();
00159 double newAvg = (myAvg * mySize + outAvg * outSize) / sampleSize_.back();
00160 average_.back() = newAvg;
00161
00162 uint totSize = sampleSize_.back();
00163 double mySum = myAvg * mySize;
00164 double outSum = outAvg * outSize;
00165 double totSum = mySum + outSum;
00166 double mySumSqr = pow(stdDev_.back(), 2) * mySize + mySum / mySize * mySum;
00167 double outSumSqr = outDev * outDev * outSize + outSum / outSize * outSum;
00168 double newDev = sqrt((mySumSqr + outSumSqr - (totSum / totSize * totSum)) / totSize);
00169 stdDev_.back() = newDev;
00170 }
00171 else {
00172 average_.back() = outAvg;
00173 stdDev_.back() = outDev;
00174 sampleSize_.back() = outSize;
00175 }
00176
00177 return true;
00178 }
00179
00180
00184 std::vector<double> StatCalc::getStats(int gen)
00185 {
00186 if(gen == -1)
00187 gen = statNo;
00188
00189 std::vector<double> stats;
00190 stats.push_back(min_[gen]);
00191 stats.push_back(max_[gen]);
00192 stats.push_back(average_[gen]);
00193 stats.push_back(stdDev_[gen]);
00194 stats.push_back(sampleSize_[gen]);
00195 stats.push_back(time_[gen]);
00196 stats.push_back(evaluations_[gen]);
00197
00198 return stats;
00199 }
00200
00201
00205 void StatCalc::log(int generation)
00206 {
00207 if(generation == -1)
00208 generation = statNo;
00209
00210 ECF_LOG(state_, 3, "Evaluations: " + uint2str(evaluations_[generation]) +
00211 "\nStats: fitness\n\tmax: " + dbl2str(max_[generation]) + "\n\tmin: " +
00212 dbl2str(min_[generation]) + "\n\tavg: " + dbl2str(average_[generation]) + "\n\tstdev: " + dbl2str(stdDev_[generation]) + "\n");
00213 }
00214
00215
00216
00217 void StatCalc::output(uint step)
00218 {
00219 std::stringstream log;
00220 for(uint i = 0; i < min_.size(); i += step)
00221 log << i << "\t" << min_[i] << std::endl;
00222 ECF_LOG(state_, 2, log.str());
00223 }