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 lowest_ = highest_ = 0;
00031
00032 if(state->getRegistry()->isModified("stats.file")) {
00033 voidP sptr = state->getRegistry()->getEntry("stats.file");
00034 statsFileName_ = *((std::string*) sptr.get());
00035
00036 statsFile_.open(statsFileName_.c_str());
00037 if(!statsFile_) {
00038 throw std::string("Error: can't open stats file (") + statsFileName_ + ")";
00039 }
00040 }
00041 return true;
00042 }
00043
00044
00048 double StatCalc::getFitnessMin(int generation)
00049 {
00050 if(generation == -1)
00051 generation = statNo;
00052 return min_[generation];
00053 }
00054
00055
00059 double StatCalc::getFitnessMax(int generation)
00060 {
00061 if(generation == -1)
00062 generation = statNo;
00063 return max_[generation];
00064 }
00065
00066
00071 bool StatCalc::operate(const std::vector<IndividualP>& pool)
00072 {
00073 std::vector<double> fitnessTemp;
00074
00075 sampleSize_.push_back((uint)pool.size());
00076 fitnessTemp.resize(pool.size());
00077
00078 for(uint i = 0; i < pool.size(); i++)
00079 fitnessTemp[i] = pool[i]->fitness->getValue();
00080
00081 max_.push_back(fitnessTemp[0]);
00082 min_.push_back(fitnessTemp[0]);
00083 statNo = (uint) max_.size() - 1;
00084 double sum = 0;
00085
00086 for(uint i = 0; i < fitnessTemp.size(); i++) {
00087 if(fitnessTemp[i] > max_[statNo]) {
00088 max_[statNo] = fitnessTemp[i];
00089 }
00090 if(fitnessTemp[i] < min_[statNo]) {
00091 min_[statNo] = fitnessTemp[i];
00092 }
00093 sum += fitnessTemp[i];
00094 }
00095
00096 average_.push_back(sum / fitnessTemp.size());
00097
00098
00099 if(min_.size() > 1) {
00100 if(min_[statNo] < lowest_)
00101 lowest_ = min_[statNo];
00102 if(max_[statNo] > highest_)
00103 highest_ = max_[statNo];
00104 } else {
00105 lowest_ = min_[0];
00106 highest_ = max_[0];
00107 }
00108
00109
00110 if(fitnessTemp.size() > 1) {
00111 double numerator = 0, denominator;
00112 for(uint i = 0; i < fitnessTemp.size(); i++) {
00113 numerator += ((fitnessTemp[i] - average_[statNo]) * (fitnessTemp[i] - average_[statNo]));
00114 }
00115 denominator = (fitnessTemp.size() - 1);
00116 stdDev_.push_back(sqrt(numerator / denominator));
00117 }
00118 else
00119 stdDev_.push_back(fitnessTemp[0]);
00120
00121 time_.push_back(state_->getElapsedTime());
00122
00123 evaluations_.push_back(nEvaluations_);
00124
00125 return true;
00126 }
00127
00128
00132 void StatCalc::copyStats(StatCalcP stats)
00133 {
00134 std::vector<double> exStats = stats->getStats();
00135 min_.push_back(exStats[0]);
00136 max_.push_back(exStats[1]);
00137 average_.push_back(exStats[2]);
00138 stdDev_.push_back(exStats[3]);
00139 sampleSize_.push_back((uint) exStats[4]);
00140 time_.push_back((uint) exStats[5]);
00141 evaluations_.push_back((uint) exStats[6]);
00142 lowest_ = exStats[ECF::FIT_LOW];
00143 highest_ = exStats[ECF::FIT_HIGH];
00144
00145 nEvaluations_ = evaluations_.back();
00146 statNo = (uint) max_.size() - 1;
00147 }
00148
00149
00153 bool StatCalc::update(std::vector<double> stats)
00154 {
00155 double outMin = stats[0];
00156 double outMax = stats[1];
00157 double outAvg = stats[2];
00158 double outDev = stats[3];
00159 uint outSize = (uint) stats[4];
00160 uint outEval = (uint) stats[6];
00161
00162 if(outMin < min_.back())
00163 min_.back() = outMin;
00164
00165 if(outMax > max_.back())
00166 max_.back() = outMax;
00167
00168 evaluations_.back() += outEval;
00169 nEvaluations_ = evaluations_.back();
00170
00171 uint mySize = sampleSize_.back();
00172 if(mySize > 1) {
00173 sampleSize_.back() = mySize + outSize;
00174 double myAvg = average_.back();
00175 double newAvg = (myAvg * mySize + outAvg * outSize) / sampleSize_.back();
00176 average_.back() = newAvg;
00177
00178 uint totSize = sampleSize_.back();
00179 double mySum = myAvg * mySize;
00180 double outSum = outAvg * outSize;
00181 double totSum = mySum + outSum;
00182 double mySumSqr = pow(stdDev_.back(), 2) * mySize + mySum / mySize * mySum;
00183 double outSumSqr = outDev * outDev * outSize + outSum / outSize * outSum;
00184 double newDev = sqrt((mySumSqr + outSumSqr - (totSum / totSize * totSum)) / totSize);
00185 stdDev_.back() = newDev;
00186 }
00187 else {
00188 average_.back() = outAvg;
00189 stdDev_.back() = outDev;
00190 sampleSize_.back() = outSize;
00191 }
00192
00193 if(stats[ECF::FIT_LOW] < lowest_)
00194 lowest_ = stats[ECF::FIT_LOW];
00195 if(stats[ECF::FIT_HIGH] > highest_)
00196 highest_ = stats[ECF::FIT_HIGH];
00197
00198 return true;
00199 }
00200
00201
00205 std::vector<double> StatCalc::getStats(int gen)
00206 {
00207 if(gen == -1)
00208 gen = statNo;
00209
00210 std::vector<double> stats;
00211 stats.push_back(min_[gen]);
00212 stats.push_back(max_[gen]);
00213 stats.push_back(average_[gen]);
00214 stats.push_back(stdDev_[gen]);
00215 stats.push_back(sampleSize_[gen]);
00216 stats.push_back(time_[gen]);
00217 stats.push_back(evaluations_[gen]);
00218 stats.push_back(lowest_);
00219 stats.push_back(highest_);
00220
00221 return stats;
00222 }
00223
00224
00228 void StatCalc::log(int generation)
00229 {
00230 if(generation == -1)
00231 generation = statNo;
00232
00233 ECF_LOG(state_, 3, "Evaluations: " + uint2str(evaluations_[generation]) +
00234 "\nStats: fitness\n\tmax: " + dbl2str(max_[generation]) + "\n\tmin: " +
00235 dbl2str(min_[generation]) + "\n\tavg: " + dbl2str(average_[generation]) + "\n\tstdev: " + dbl2str(stdDev_[generation]) + "\n");
00236 }
00237
00238
00239
00240 void StatCalc::output(uint step)
00241 {
00242 std::stringstream log;
00243 for(uint i = 0; i < min_.size(); i += step)
00244 log << i << "\t" << min_[i] << std::endl;
00245 ECF_LOG(state_, 2, log.str());
00246 }