1 /*
2  *  cStats.cc
3  *  Avida
4  *
5  *  Called "stats.cc" prior to 12/5/05.
6  *  Copyright 1999-2011 Michigan State University. All rights reserved.
7  *  Copyright 1993-2001 California Institute of Technology.
8  *
9  *
10  *  This file is part of Avida.
11  *
12  *  Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
13  *  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
14  *
15  *  Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public License along with Avida.
19  *  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include "cStats.h"
24 
25 #include "avida/core/WorldDriver.h"
26 #include "avida/data/Manager.h"
27 #include "avida/data/Package.h"
28 
29 #include "cBioGroup.h"
30 #include "cDataFile.h"
31 #include "cEnvironment.h"
32 #include "cHardwareBase.h"
33 #include "cHardwareManager.h"
34 #include "cInstSet.h"
35 #include "cPopulation.h"
36 #include "cPopulationCell.h"
37 #include "cDeme.h"
38 #include "cMigrationMatrix.h" // MIGRATION_MATRIX
39 #include "cStringUtil.h"
40 #include "cWorld.h"
41 #include "tDataEntry.h"
42 #include "cOrgMessage.h"
43 #include "cOrgMessagePredicate.h"
44 #include "cOrgMovementPredicate.h"
45 #include "cReaction.h"
46 #include "cEventList.h"
47 
48 #include <algorithm>
49 #include <cfloat>
50 #include <numeric>
51 #include <cmath>
52 #include <sstream>
53 
54 using namespace Avida;
55 using namespace AvidaTools;
56 
57 
cStats(cWorld * world)58 cStats::cStats(cWorld* world)
59   : m_world(world)
60   , m_data_manager(this, "population_data")
61   , m_update(-1)
62   , avida_time(0)
63   , rave_true_replication_rate( 500 )
64   , entropy(0.0)
65   , species_entropy(0.0)
66   , energy(0.0)
67   , dom_fidelity(0.0)
68   , ave_fidelity(0.0)
69   , max_viable_fitness(0)
70   , dom_merit(0)
71   , dom_gestation(0)
72   , dom_repro_rate(0)
73   , dom_fitness(0)
74   , dom_size(0)
75   , dom_copied_size(0)
76   , dom_exe_size(0)
77   , max_fitness(0)
78   , max_merit(0)
79   , max_gestation_time(0)
80   , max_genome_length(0)
81   , min_fitness(FLT_MAX)
82   , min_merit(FLT_MAX)
83   , min_gestation_time(INT_MAX)
84   , min_genome_length(INT_MAX)
85   , dom_genotype_id(-1)
86   , dom_name("(none)")
87   , dom_births(0)
88   , dom_breed_true(0)
89   , dom_breed_in(0)
90   , dom_breed_out(0)
91   , dom_abundance(0)
92   , dom_gene_depth(-1)
93   , dom_sequence("")
94   , dom_last_birth_cell(0)
95   , dom_last_forager_type(-1)
96   , dom_last_group_id(-1)
97   , coal_depth(0)
98   , num_births(0)
99   , num_deaths(0)
100   , num_breed_in(0)
101   , num_breed_true(0)
102   , num_breed_true_creatures(0)
103   , num_creatures(0)
104   , num_genotypes(0)
105   , num_genotypes_historic(0)
106   , num_threshold(0)
107   , num_lineages(0)
108   , num_executed(0)
109   , num_parasites(0)
110   , num_no_birth_creatures(0)
111   , num_single_thread_creatures(0)
112   , num_multi_thread_creatures(0)
113   , m_num_threads(0)
114   , num_modified(0)
115   , num_genotypes_last(1)
116   , num_kabooms(0)
117   , num_kaboom_kills(0)
118   , tot_organisms(0)
119   , tot_genotypes(0)
120   , tot_threshold(0)
121   , tot_lineages(0)
122   , tot_executed(0)
123   , num_resamplings(0)
124   , num_failedResamplings(0)
125   , last_update(0)
126   , num_bought(0)
127   , num_sold(0)
128   , num_used(0)
129   , num_own_used(0)
130   , sense_size(0)
131   , avg_competition_fitness(0)
132   , min_competition_fitness(0)
133   , max_competition_fitness(0)
134   , avg_competition_copied_fitness(0)
135   , min_competition_copied_fitness(0)
136   , max_competition_copied_fitness(0)
137   , num_orgs_replicated(0)
138   , m_spec_total(0)
139   , m_spec_num(0)
140   , m_spec_waste(0)
141   , num_migrations(0)
142   , m_num_successful_mates(0)
143   , prey_entropy(0.0)
144   , pred_entropy(0.0)
145   , topreac(-1)
146   , topcycle(-1)
147   , m_deme_num_repls(0)
148 	, m_deme_num_repls_treatable(0)
149 	, m_deme_num_repls_untreatable(0)
150   , m_donate_to_donor (0)
151   , m_donate_to_facing (0)
152 {
153   const cEnvironment& env = m_world->GetEnvironment();
154   const int num_tasks = env.GetNumTasks();
155 
156   task_cur_count.Resize(num_tasks);
157   task_last_count.Resize(num_tasks);
158 
159   tasks_host_current.Resize(num_tasks);
160   tasks_host_last.Resize(num_tasks);
161   tasks_parasite_current.Resize(num_tasks);
162   tasks_parasite_last.Resize(num_tasks);
163 
164   task_cur_quality.Resize(num_tasks);
165   task_last_quality.Resize(num_tasks);
166   task_cur_max_quality.Resize(num_tasks);
167   task_last_max_quality.Resize(num_tasks);
168   task_exe_count.Resize(num_tasks);
169   new_task_count.Resize(num_tasks);
170   prev_task_count.Resize(num_tasks);
171   cur_task_count.Resize(num_tasks);
172   new_reaction_count.Resize(env.GetNumReactions());
173   task_cur_count.SetAll(0);
174   task_cur_quality.SetAll(0);
175   task_cur_max_quality.SetAll(0);
176   task_last_max_quality.SetAll(0);
177   task_last_quality.SetAll(0);
178   task_last_count.SetAll(0);
179   task_cur_max_quality.SetAll(0);
180   task_last_max_quality.SetAll(0);
181   task_exe_count.SetAll(0);
182   new_task_count.SetAll(0);
183   prev_task_count.SetAll(0);
184   cur_task_count.SetAll(0);
185   new_reaction_count.SetAll(0);
186 
187   // Stats for internal resource use
188   task_internal_cur_count.Resize(num_tasks);
189   task_internal_last_count.Resize(num_tasks);
190   task_internal_cur_quality.Resize(num_tasks);
191   task_internal_last_quality.Resize(num_tasks);
192   task_internal_cur_max_quality.Resize(num_tasks);
193   task_internal_last_max_quality.Resize(num_tasks);
194   task_internal_cur_count.SetAll(0);
195   task_internal_last_count.SetAll(0);
196   task_internal_cur_quality.SetAll(0.0);
197   task_internal_last_quality.SetAll(0.0);
198   task_internal_cur_max_quality.SetAll(0.0);
199   task_internal_last_max_quality.SetAll(0.0);
200 
201 
202   ZeroInst();
203   ZeroFTInst();
204 
205   const int num_reactions = env.GetNumReactions();
206   m_reaction_cur_count.Resize(num_reactions);
207   m_reaction_last_count.Resize(num_reactions);
208   m_reaction_cur_add_reward.Resize(num_reactions);
209   m_reaction_last_add_reward.Resize(num_reactions);
210   m_reaction_exe_count.Resize(num_reactions);
211   m_reaction_cur_count.SetAll(0);
212   m_reaction_last_count.SetAll(0);
213   m_reaction_cur_add_reward.SetAll(0.0);
214   m_reaction_last_add_reward.SetAll(0.0);
215   m_reaction_exe_count.SetAll(0);
216 
217 
218   resource_count.Resize( m_world->GetNumResources() );
219   resource_count.SetAll(0);
220 
221   resource_geometry.Resize( m_world->GetNumResources() );
222   resource_geometry.SetAll(nGeometry::GLOBAL);
223 
224   task_names.Resize(num_tasks);
225   for (int i = 0; i < num_tasks; i++) task_names[i] = env.GetTask(i).GetDesc();
226 
227   reaction_names.Resize(num_reactions);
228   for (int i = 0; i < num_reactions; i++) reaction_names[i] = env.GetReactionName(i);
229 
230   resource_names.Resize( m_world->GetNumResources() );
231 
232   m_resource_print_thresh = m_world->GetConfig().RES_FOR_DEME_REP.Get();
233 
234   // This block calculates how many slots we need to
235   // make for paying attention to different label combinations
236   // Require sense instruction to be present then die if not at least 2 NOPs
237 
238   // @DMB - This code makes assumptions about instruction sets that may not hold true under multiple inst sets.
239   //      - This sort of functionality should be reimplemented as instruction set stats or something similar
240 //  bool sense_used = m_world->GetHardwareManager().GetInstSet().InstInSet( cStringUtil::Stringf("sense") )
241 //                ||  m_world->GetHardwareManager().GetInstSet().InstInSet( cStringUtil::Stringf("sense-unit") )
242 //                ||  m_world->GetHardwareManager().GetInstSet().InstInSet( cStringUtil::Stringf("sense-m100") );
243 //  if (sense_used)
244 //  {
245 //    if (m_world->GetHardwareManager().GetInstSet().GetNumNops() < 2)
246 //    {
247 //      cerr << "Error: If you have a sense instruction in your instruction set, then";
248 //      cerr << "you MUST also include at least two NOPs in your instruction set. " << endl; exit(1);
249 //    }
250 //
251 //    int on = 1;
252 //    int max_sense_label_length = 0;
253 //    while (on < m_world->GetNumResources())
254 //    {
255 //      max_sense_label_length++;
256 //      sense_size += on;
257 //      on *= m_world->GetHardwareManager().GetInstSet().GetNumNops();
258 //    }
259 //    sense_size += on;
260 //
261 //    sense_last_count.Resize( sense_size );
262 //    sense_last_count.SetAll(0);
263 //
264 //    sense_last_exe_count.Resize( sense_size );
265 //    sense_last_exe_count.SetAll(0);
266 //
267 //    sense_names.Resize( sense_size );
268 //    int assign_index = 0;
269 //    int num_per = 1;
270 //    for (int i=0; i<= max_sense_label_length; i++)
271 //    {
272 //      for (int j=0; j< num_per; j++)
273 //      {
274 //        sense_names[assign_index] = (on > 1) ?
275 //          cStringUtil::Stringf("sense_res.%i-%i", j*on, (j+1)*on-1) :
276 //          cStringUtil::Stringf("sense_res.%i", j);
277 //
278 //        assign_index++;
279 //      }
280 //      on /= m_world->GetHardwareManager().GetInstSet().GetNumNops();
281 //      num_per *= m_world->GetHardwareManager().GetInstSet().GetNumNops();
282 //    }
283 //  }
284   // End sense tracking initialization
285 
286   if(m_world->GetConfig().NUM_DEMES.Get() == 0) {
287     relative_pos_event_count.ResizeClear(m_world->GetConfig().WORLD_X.Get(), m_world->GetConfig().WORLD_Y.Get());
288     relative_pos_pred_sat.ResizeClear(m_world->GetConfig().WORLD_X.Get(), m_world->GetConfig().WORLD_Y.Get());
289   } else {
290     relative_pos_event_count.ResizeClear(m_world->GetConfig().WORLD_X.Get(), m_world->GetConfig().WORLD_Y.Get() / m_world->GetConfig().NUM_DEMES.Get());
291     relative_pos_pred_sat.ResizeClear(m_world->GetConfig().WORLD_X.Get(), m_world->GetConfig().WORLD_Y.Get() / m_world->GetConfig().NUM_DEMES.Get());
292   }
293 
294   relative_pos_event_count.SetAll(0);
295   relative_pos_pred_sat.SetAll(0);
296 
297   setupProvidedData();
298 }
299 
300 
NotifyBGEvent(cBioGroup * bg,eBGEventType type,cBioUnit * bu)301 void cStats::NotifyBGEvent(cBioGroup* bg, eBGEventType type, cBioUnit* bu)
302 {
303   assert(bg);
304 
305   switch (type) {
306     case BG_EVENT_ADD_THRESHOLD:
307       num_threshold++;
308       tot_threshold++;
309       if (m_world->GetConfig().LOG_THRESHOLD.Get()) {
310         cDataFile& df = m_world->GetDataFile("threshold.log");
311         df.Write(m_update, "Update");
312         df.Write(bg->GetID(), "ID");
313         df.Write(bg->GetProperty("name").AsString(), "Name");
314         df.Endl();
315       }
316       break;
317 
318     case BG_EVENT_REMOVE_THRESHOLD:
319       num_threshold--;
320       break;
321   }
322 
323 }
324 
325 
Provides() const326 Data::ConstDataSetPtr cStats::Provides() const
327 {
328   if (!m_provides) {
329     Data::DataSetPtr provides(new Apto::Set<Apto::String>);
330     for (Apto::Map<Apto::String, ProvidedData>::KeyIterator it = m_provided_data.Keys(); it.Next();) {
331       provides->Insert(*it.Get());
332     }
333     m_provides = provides;
334   }
335   return m_provides;
336 }
337 
UpdateProvidedValues(Update current_update)338 void cStats::UpdateProvidedValues(Update current_update)
339 {
340   // Nothing for now, all handled by ProcessUpdate()
341 }
342 
GetProvidedValue(const Apto::String & data_id) const343 Data::PackagePtr cStats::GetProvidedValue(const Apto::String& data_id) const
344 {
345   ProvidedData data_entry;
346   Data::PackagePtr rtn;
347   if (m_provided_data.Get(data_id, data_entry)) {
348     rtn = data_entry.GetData();
349   }
350   assert(rtn);
351   return rtn;
352 }
353 
DescribeProvidedValue(const Apto::String & data_id) const354 Apto::String cStats::DescribeProvidedValue(const Apto::String& data_id) const
355 {
356   ProvidedData data_entry;
357   Apto::String rtn;
358   if (m_provided_data.Get(data_id, data_entry)) {
359     rtn = data_entry.description;
360   }
361   assert(rtn != "");
362   return rtn;
363 }
364 
365 
packageData(T (cStats::* func)()const) const366 template <class T> Data::PackagePtr cStats::packageData(T (cStats::*func)() const) const
367 {
368   return Data::PackagePtr(new Data::Wrap<T>((this->*func)()));
369 }
370 
371 
setupProvidedData()372 void cStats::setupProvidedData()
373 {
374   // Load in all the keywords, descriptions, and associated functions for
375   // data management.
376 
377   // Setup functors and references for use in the PROVIDE macro
378   Data::ProviderActivateFunctor activate(m_world, &cWorld::GetStatsProvider);
379   Data::Manager& mgr = m_world->GetDataManager();
380   Apto::Functor<Data::PackagePtr, Apto::TL::Create<int (cStats::*)() const> > intStat(this, &cStats::packageData<int>);
381   Apto::Functor<Data::PackagePtr, Apto::TL::Create<double (cStats::*)() const> > doubleStat(this, &cStats::packageData<double>);
382 
383   // Define PROVIDE macro to simplify instantiating new provided data
384 #define PROVIDE(name, desc, type, func) { \
385   m_provided_data[name] = ProvidedData(desc, Apto::BindFirst(type ## Stat, &cStats::func));\
386   mgr.Register(name, activate); \
387 }
388 
389   // Time Stats
390   m_data_manager.Add("update",      "Update",      &cStats::GetUpdate);
391   m_data_manager.Add("generation",  "Generation",  &cStats::GetGeneration);
392 
393   PROVIDE("core.update",                   "Update",                               int,    GetUpdate);
394   PROVIDE("core.world.ave_generation",     "Average Generation",                   double, GetGeneration);
395 
396 
397   // Population Level Stats
398   m_data_manager.Add("entropy",         "Genotype Entropy (Diversity)", &cStats::GetEntropy);
399   m_data_manager.Add("species_entropy", "Species Entropy (Diversity)",  &cStats::GetEntropy);
400   m_data_manager.Add("energy",          "Average Inferiority (Energy)", &cStats::GetEnergy);
401   m_data_manager.Add("richness",        "Number of Different Genotypes (Richness)", &cStats::GetNumGenotypes);
402   m_data_manager.Add("eveness",         "Equitability of Genotype Distribution (Evenness)", &cStats::GetEvenness);
403   m_data_manager.Add("coal_depth",      "Depth of Coalescent Genotype", &cStats::GetCoalescentDepth);
404   m_data_manager.Add("num_resamplings",  "Total Number of resamplings this time step", &cStats::GetResamplings);
405   m_data_manager.Add("num_failedResamplings",  "Total Number of divide commands that reached the resampling hard-cap this time step", &cStats::GetFailedResamplings);
406 
407 
408   // Dominant Genotype Stats
409   m_data_manager.Add("dom_merit",      "Ave Merit of Dominant Genotype",          &cStats::GetDomMerit);
410   m_data_manager.Add("dom_gest",       "Ave Gestation Time of Dominant Genotype", &cStats::GetDomGestation);
411   m_data_manager.Add("dom_fitness",    "Ave Fitness of Dominant Genotype",        &cStats::GetDomFitness);
412   m_data_manager.Add("dom_repro",      "Ave Repro-Rate of Dominant Genotype",     &cStats::GetDomReproRate);
413   m_data_manager.Add("dom_length",     "Genome Length of Dominant Genotype",      &cStats::GetDomSize);
414   m_data_manager.Add("dom_copy_length","Copied Length of Dominant Genotype",      &cStats::GetDomCopySize);
415   m_data_manager.Add("dom_exe_length", "Executed Length of Dominant Genotype",    &cStats::GetDomExeSize);
416   m_data_manager.Add("dom_id",         "ID of Dominant Genotype",                 &cStats::GetDomID);
417   m_data_manager.Add("dom_name",       "Name of Dominant Genotype",               &cStats::GetDomName);
418   m_data_manager.Add("dom_births",     "Birth Count of Dominant Genotype",        &cStats::GetDomBirths);
419   m_data_manager.Add("dom_breed_true", "Breed-True Count  of Dominant Genotype",  &cStats::GetDomBreedTrue);
420   m_data_manager.Add("dom_breed_in",   "Breed-In Count of Dominant Genotype",     &cStats::GetDomBreedIn);
421   m_data_manager.Add("dom_breed_out",  "Breed-Out Count of Dominant Genotype",    &cStats::GetDomBreedOut);
422   m_data_manager.Add("dom_num_cpus",   "Abundance of Dominant Genotype",          &cStats::GetDomAbundance);
423   m_data_manager.Add("dom_depth",      "Tree Depth of Dominant Genotype",         &cStats::GetDomGeneDepth);
424   m_data_manager.Add("dom_sequence",   "Sequence of Dominant Genotype",           &cStats::GetDomSequence);
425   m_data_manager.Add("dom_last_birth_cell", "Birth Cell of Last-Born Dominant Genotype", &cStats::GetDomLastBirthCell);
426   m_data_manager.Add("dom_last_group_id", "Birth Group ID of Last-Born Dominant Genotype", &cStats::GetDomLastGroup);
427   m_data_manager.Add("dom_last_forager_type", "Birth Forager Type of Last-Born Dominant Genotype", &cStats::GetDomLastForagerType);
428 
429   // Current Counts...
430   m_data_manager.Add("num_births",     "Count of Births in Population",          &cStats::GetNumBirths);
431   m_data_manager.Add("num_deaths",     "Count of Deaths in Population",          &cStats::GetNumDeaths);
432   m_data_manager.Add("breed_in",       "Count of Non-Breed-True Births",         &cStats::GetBreedIn);
433   m_data_manager.Add("breed_true",     "Count of Breed-True Births",             &cStats::GetBreedTrue);
434   m_data_manager.Add("bred_true",      "Count of Organisms that have Bred True", &cStats::GetBreedTrueCreatures);
435   m_data_manager.Add("num_cpus",       "Count of Organisms in Population",       &cStats::GetNumCreatures);
436   m_data_manager.Add("num_genotypes",  "Count of Genotypes in Population",       &cStats::GetNumGenotypes);
437   m_data_manager.Add("num_genotypes_historic", "Count of Historic Genotypes",    &cStats::GetNumGenotypesHistoric);
438   m_data_manager.Add("num_threshold",  "Count of Threshold Genotypes",           &cStats::GetNumThreshold);
439   m_data_manager.Add("num_lineages",   "Count of Lineages in Population",        &cStats::GetNumLineages);
440   m_data_manager.Add("num_parasites",  "Count of Parasites in Population",       &cStats::GetNumParasites);
441   m_data_manager.Add("threads",        "Count of Threads in Population",         &cStats::GetNumThreads);
442   m_data_manager.Add("num_no_birth",   "Count of Childless Organisms",           &cStats::GetNumNoBirthCreatures);
443 
444   PROVIDE("core.world.organisms",          "Count of Organisms in the World",      int,    GetNumCreatures);
445 
446 
447   // Total Counts...
448   m_data_manager.Add("tot_cpus",      "Total Organisms ever in Population", &cStats::GetTotCreatures);
449   m_data_manager.Add("tot_genotypes", "Total Genotypes ever in Population", &cStats::GetTotGenotypes);
450   m_data_manager.Add("tot_threshold", "Total Threshold Genotypes Ever",     &cStats::GetTotThreshold);
451   m_data_manager.Add("tot_lineages",  "Total Lineages ever in Population",  &cStats::GetTotLineages);
452 
453 
454   // Some Average Data...
455   m_data_manager.Add("ave_repro_rate", "Average Repro-Rate (1/Gestation)", &cStats::GetAveReproRate);
456   m_data_manager.Add("ave_merit",      "Average Merit",                    &cStats::GetAveMerit);
457   m_data_manager.Add("ave_age",        "Average Age",                      &cStats::GetAveCreatureAge);
458   m_data_manager.Add("ave_memory",     "Average Memory Used",              &cStats::GetAveMemSize);
459   m_data_manager.Add("ave_neutral",    "Average Neutral Metric",           &cStats::GetAveNeutralMetric);
460   m_data_manager.Add("ave_lineage",    "Average Lineage Label",            &cStats::GetAveLineageLabel);
461   m_data_manager.Add("ave_gest",       "Average Gestation Time",           &cStats::GetAveGestation);
462   m_data_manager.Add("ave_fitness",    "Average Fitness",                  &cStats::GetAveFitness);
463   m_data_manager.Add("ave_gen_age",    "Average Genotype Age",             &cStats::GetAveGenotypeAge);
464   m_data_manager.Add("ave_length",     "Average Genome Length",            &cStats::GetAveSize);
465   m_data_manager.Add("ave_copy_length","Average Copied Length",            &cStats::GetAveCopySize);
466   m_data_manager.Add("ave_exe_length", "Average Executed Length",          &cStats::GetAveExeSize);
467   m_data_manager.Add("ave_thresh_age", "Average Threshold Genotype Age",   &cStats::GetAveThresholdAge);
468 
469   m_data_manager.Add("ave_speculative","Averate Speculative Instructions", &cStats::GetAveSpeculative);
470   m_data_manager.Add("speculative_waste", "Speculative Execution Waste",   &cStats::GetSpeculativeWaste);
471 
472   PROVIDE("core.world.ave_metabolic_rate", "Average Metabolic Rate",               double, GetAveMerit);
473   PROVIDE("core.world.ave_age",            "Average Organism Age (in updates)",    double, GetAveCreatureAge);
474   PROVIDE("core.world.ave_gestation_time", "Average Gestation Time",               double, GetAveGestation);
475   PROVIDE("core.world.ave_fitness",        "Average Fitness",                      double, GetAveFitness);
476 
477 
478   // Maximums
479   m_data_manager.Add("max_fitness", "Maximum Fitness in Population", &cStats::GetMaxFitness);
480   m_data_manager.Add("max_merit",   "Maximum Merit in Population",   &cStats::GetMaxMerit);
481 
482 
483   // Minimums
484   m_data_manager.Add("min_fitness", "Minimum Fitness in Population", &cStats::GetMinFitness);
485 
486 #undef PROVIDE
487 }
488 
ZeroTasks()489 void cStats::ZeroTasks()
490 {
491   task_cur_count.SetAll(0);
492   task_last_count.SetAll(0);
493 
494   tasks_host_current.SetAll(0);
495   tasks_host_last.SetAll(0);
496   tasks_parasite_current.SetAll(0);
497   tasks_parasite_last.SetAll(0);
498 
499   task_cur_quality.SetAll(0);
500   task_last_quality.SetAll(0);
501   task_last_max_quality.SetAll(0);
502   task_cur_max_quality.SetAll(0);
503   task_internal_cur_count.SetAll(0);
504   task_internal_cur_quality.SetAll(0);
505   task_internal_cur_max_quality.SetAll(0);
506   task_internal_last_count.SetAll(0);
507   task_internal_last_quality.SetAll(0);
508   task_internal_last_max_quality.SetAll(0);
509 }
510 
ZeroReactions()511 void cStats::ZeroReactions()
512 {
513   m_reaction_cur_count.SetAll(0);
514   m_reaction_last_count.SetAll(0);
515   m_reaction_cur_add_reward.SetAll(0);
516   m_reaction_last_add_reward.SetAll(0);
517 }
518 
519 
ZeroInst()520 void cStats::ZeroInst()
521 {
522   for (tArrayMap<cString, tArray<cIntSum> >::iterator it = m_is_exe_inst_map.begin(); it != m_is_exe_inst_map.end(); it++) {
523     for (int i = 0; i < (*it).Value().GetSize(); i++) (*it).Value()[i].Clear();
524   }
525 }
526 
ZeroFTInst()527 void cStats::ZeroFTInst()
528 {
529   for (tArrayMap<cString, tArray<cIntSum> >::iterator it = m_is_prey_exe_inst_map.begin(); it != m_is_prey_exe_inst_map.end(); it++) {
530     for (int i = 0; i < (*it).Value().GetSize(); i++) (*it).Value()[i].Clear();
531   }
532   for (tArrayMap<cString, tArray<cIntSum> >::iterator it = m_is_pred_exe_inst_map.begin(); it != m_is_pred_exe_inst_map.end(); it++) {
533     for (int i = 0; i < (*it).Value().GetSize(); i++) (*it).Value()[i].Clear();
534   }
535 }
536 
ZeroMTInst()537 void cStats::ZeroMTInst()
538 {
539   for (tArrayMap<cString, tArray<cIntSum> >::iterator it = m_is_male_exe_inst_map.begin(); it != m_is_male_exe_inst_map.end(); it++) {
540     for (int i = 0; i < (*it).Value().GetSize(); i++) (*it).Value()[i].Clear();
541   }
542   for (tArrayMap<cString, tArray<cIntSum> >::iterator it = m_is_female_exe_inst_map.begin(); it != m_is_female_exe_inst_map.end(); it++) {
543     for (int i = 0; i < (*it).Value().GetSize(); i++) (*it).Value()[i].Clear();
544   }
545 }
546 
CalcEnergy()547 void cStats::CalcEnergy()
548 {
549   assert(sum_fitness.Average() >= 0.0);
550   assert(dom_fitness >= 0);
551 
552 
553   // Note: When average fitness and dominant fitness are close in value (i.e. should be identical)
554   //       floating point rounding error can cause output variances.  To mitigate this, threshold
555   //       caps off values that differ by less than it, flushing the effective output value to zero.
556   const double ave_fitness = sum_fitness.Average();
557   const double threshold = 1.0e-14;
558   if (ave_fitness == 0.0 || dom_fitness == 0.0 || fabs(ave_fitness - dom_fitness) < threshold) {
559     energy = 0.0;
560   } else  {
561     energy = Log(dom_fitness / ave_fitness);
562   }
563 }
564 
CalcFidelity()565 void cStats::CalcFidelity()
566 {
567   // There is a (small) probability that when a random instruction is picked
568   // after a mutation occurs, that it will be the original instruction again;
569   // This needs to be adjusted for!
570 
571   double ave_num_insts = 0.0;
572   for (tArrayMap<cString, tArray<cString> >::iterator it = m_is_inst_names_map.begin(); it != m_is_inst_names_map.end(); it++) {
573     ave_num_insts += (*it).Value().GetSize();
574   }
575   ave_num_insts /= m_is_inst_names_map.GetSize();
576 
577   double adj = (ave_num_insts - 1.0) / ave_num_insts;
578 
579   double base_fidelity = (1.0 - adj * m_world->GetConfig().DIVIDE_MUT_PROB.Get()) *
580     (1.0 - m_world->GetConfig().DIVIDE_INS_PROB.Get()) * (1.0 - m_world->GetConfig().DIVIDE_DEL_PROB.Get());
581 
582   double true_cm_rate = adj * m_world->GetConfig().COPY_MUT_PROB.Get();
583   ave_fidelity = base_fidelity * pow(1.0 - true_cm_rate, sum_size.Average());
584   dom_fidelity = base_fidelity * pow(1.0 - true_cm_rate, dom_size);
585 }
586 
RecordBirth(bool breed_true)587 void cStats::RecordBirth(bool breed_true)
588 {
589 	if (m_world->GetEventsList()->CheckBirthInterruptQueue(tot_organisms) == true)
590 		m_world->GetEventsList()->ProcessInterrupt(m_world->GetDefaultContext());
591 
592   tot_organisms++;
593   num_births++;
594 
595   if (breed_true) num_breed_true++;
596   else num_breed_in++;
597 }
598 
RemoveGenotype(int id_num,int parent_id,int parent_dist,int depth,int max_abundance,int parasite_abundance,int age,int length)599 void cStats::RemoveGenotype(int id_num, int parent_id,
600    int parent_dist, int depth, int max_abundance, int parasite_abundance,
601    int age, int length)
602 {
603   if (m_world->GetConfig().LOG_GENOTYPES.Get() &&
604       (m_world->GetConfig().LOG_GENOTYPES.Get() != 2 || max_abundance > 2)) {
605     const int update_born = cStats::GetUpdate() - age + 1;
606     cDataFile& df = m_world->GetDataFile("genotype.log");
607     df.Write(id_num, "Genotype ID");
608     df.Write(update_born, "Update Born");
609     df.Write(parent_id, "Parent ID");
610     df.Write(parent_dist, "Parent Distance");
611     df.Write(depth, "Depth");
612     df.Write(max_abundance, "Maximum Abundance");
613     df.Write(age, "Age");
614     df.Write(length, "Length");
615     df.Endl();
616   }
617 
618   (void) parasite_abundance; // Not used now, but maybe in future.
619 }
620 
ProcessUpdate()621 void cStats::ProcessUpdate()
622 {
623   // Increment the "avida_time"
624   if (sum_merit.Count() > 0 && sum_merit.Average() > 0) {
625     double delta = ((double)(m_update-last_update))/sum_merit.Average();
626     avida_time += delta;
627 
628     // calculate the true replication rate in this update
629     rave_true_replication_rate.Add( num_births/
630 	  (delta * m_world->GetConfig().AVE_TIME_SLICE.Get() * num_creatures) );
631   }
632   last_update = m_update;
633 
634   // Zero-out any variables which need to be cleared at end of update.
635 
636   num_births = 0;
637   num_deaths = 0;
638   num_breed_true = 0;
639 
640   tot_executed += num_executed;
641   num_executed = 0;
642 
643   task_cur_count.SetAll(0);
644   task_last_count.SetAll(0);
645   task_cur_quality.SetAll(0);
646   task_last_quality.SetAll(0);
647   task_cur_max_quality.SetAll(0);
648   task_last_max_quality.SetAll(0);
649   task_exe_count.SetAll(0);
650 
651   task_internal_cur_count.SetAll(0);
652   task_internal_last_count.SetAll(0);
653   task_internal_cur_quality.SetAll(0);
654   task_internal_last_quality.SetAll(0);
655   task_internal_cur_max_quality.SetAll(0);
656   task_internal_last_max_quality.SetAll(0);
657 
658   sense_last_count.SetAll(0);
659   sense_last_exe_count.SetAll(0);
660 
661   m_reaction_cur_count.SetAll(0);
662   m_reaction_last_count.SetAll(0);
663   m_reaction_cur_add_reward.SetAll(0.0);
664   m_reaction_last_add_reward.SetAll(0.0);
665   m_reaction_exe_count.SetAll(0);
666 
667   dom_merit = 0;
668   dom_gestation = 0.0;
669   dom_fitness = 0.0;
670   max_fitness = 0.0;
671 
672   num_resamplings = 0;
673   num_failedResamplings = 0;
674 
675   m_spec_total = 0;
676   m_spec_num = 0;
677   m_spec_waste = 0;
678 
679   num_migrations = 0;
680 
681   m_num_successful_mates = 0;
682 }
683 
RemoveLineage(int id_num,int parent_id,int update_born,double generation_born,int total_CPUs,int total_genotypes,double fitness,double lineage_stat1,double lineage_stat2)684 void cStats::RemoveLineage(int id_num, int parent_id, int update_born, double generation_born, int total_CPUs,
685                            int total_genotypes, double fitness, double lineage_stat1, double lineage_stat2 )
686 {
687   num_lineages--;
688   if (m_world->GetConfig().LOG_LINEAGES.Get()) {
689     cDataFile& lineage_log = m_world->GetDataFile("lineage.log");
690 
691     lineage_log.WriteComment("Columns 10, 11 depend on lineage creation method chosen.");
692 
693     lineage_log.Write(id_num, "lineage id");
694     lineage_log.Write(parent_id, "parent lineage id");
695     lineage_log.Write(fitness, "initial fitness");
696     lineage_log.Write(total_CPUs, "total number of creatures");
697     lineage_log.Write(total_genotypes, "total number of genotypes");
698     lineage_log.Write(update_born, "update born");
699     lineage_log.Write(cStats::GetUpdate(), "update extinct");
700     lineage_log.Write(generation_born, "generation born");
701     lineage_log.Write(SumGeneration().Average(), "generation extinct");
702     lineage_log.Write(lineage_stat1, "lineage stat1");
703     lineage_log.Write(lineage_stat2, "lineage stat2");
704     lineage_log.Endl();
705   }
706 }
707 
GetNumPreyCreatures() const708 int cStats::GetNumPreyCreatures() const
709 {
710   return m_world->GetPopulation().GetNumPreyOrganisms();
711 }
712 
GetNumPredCreatures() const713 int cStats::GetNumPredCreatures() const
714 {
715   return m_world->GetPopulation().GetNumPredOrganisms();
716 }
717 
PrintDataFile(const cString & filename,const cString & format,char sep)718 void cStats::PrintDataFile(const cString& filename, const cString& format, char sep)
719 {
720   cDataFile& data_file = m_world->GetDataFile(filename);
721   m_data_manager.PrintRow(data_file, format, sep);
722 }
723 
724 
PrintAverageData(const cString & filename)725 void cStats::PrintAverageData(const cString& filename)
726 {
727   cDataFile& df = m_world->GetDataFile(filename);
728 
729   df.WriteComment("Avida Average Data");
730   df.WriteTimeStamp();
731 
732   df.Write(m_update,                "Update");
733   df.Write(sum_merit.Average(),           "Merit");
734   df.Write(sum_gestation.Average(),       "Gestation Time");
735   df.Write(sum_fitness.Average(),         "Fitness");
736   df.Write(sum_repro_rate.Average(),      "Repro Rate?");
737   df.Write(sum_size.Average(),            "Size");
738   df.Write(sum_copy_size.Average(),       "Copied Size");
739   df.Write(sum_exe_size.Average(),        "Executed Size");
740   df.Write(sum_abundance.Average(),       "Abundance");
741 
742   // The following causes births and breed true to default to 0.0 when num_creatures is 0
743   double ave_births = 0.0;
744   double ave_breed_true = 0.0;
745   if (num_creatures > 0) {
746     const double d_num_creatures = static_cast<double>(num_creatures);
747     ave_births = static_cast<double>(num_births) / d_num_creatures;
748     ave_breed_true = static_cast<double>(num_breed_true) / d_num_creatures;
749   }
750   df.Write(ave_births,                    "Proportion of organisms that gave birth in this update");
751   df.Write(ave_breed_true,                "Proportion of Breed True Organisms");
752 
753   df.Write(sum_genotype_depth.Average(),  "Genotype Depth");
754   df.Write(sum_generation.Average(),      "Generation");
755   df.Write(sum_neutral_metric.Average(),  "Neutral Metric");
756   df.Write(sum_lineage_label.Average(),   "Lineage Label");
757   df.Write(rave_true_replication_rate.Average(), "True Replication Rate (based on births/update, time-averaged)");
758   df.Endl();
759 }
760 
PrintDemeAverageData(const cString & filename)761 void cStats::PrintDemeAverageData(const cString& filename)
762 {
763   cDataFile& df = m_world->GetDataFile(filename);
764 
765   df.WriteComment("Avida Average Deme Data");
766   df.WriteTimeStamp();
767 
768   df.Write(m_update,                                        "Update");
769   df.Write(m_num_occupied_demes,                            "Count");
770   df.Write(sum_deme_age.Average(),                          "Age");
771   df.Write(sum_deme_birth_count.Average(),                  "Births");
772   df.Write(sum_deme_org_count.Average(),                    "Organisms");
773   df.Write(sum_deme_generation.Average(),                   "Generation");
774   df.Write(sum_deme_last_birth_count.Average(),                  "Births (at last replication)");
775   df.Write(sum_deme_last_org_count.Average(),                    "Organisms (at last replication)");
776   df.Write(sum_deme_merit.Average(),                        "Merit");
777   df.Write(sum_deme_gestation_time.Average(),               "Gestation Time");
778   df.Write(sum_deme_normalized_time_used.Average(),         "Time Used (normalized by org fitness)");
779   df.Write(sum_deme_generations_per_lifetime.Average(),     "Generations between current and last founders");
780   df.Write(sum_deme_events_killed.Average(),                "Events killed");
781   df.Write(sum_deme_events_kill_attempts.Average(),         "Attempts to kill event");
782 
783   df.Endl();
784 }
785 
PrintFlowRateTuples(const cString & filename)786 void cStats::PrintFlowRateTuples(const cString& filename) {
787   cDataFile& df = m_world->GetDataFile(filename);
788 
789   df.WriteComment("Flow Rate Tuples");
790   df.WriteTimeStamp();
791 
792   df.Write(m_update,                                        "Update");
793   // write each tuple
794   for(map<int, flow_rate_tuple>::iterator iter = flow_rate_tuples.begin(); iter != flow_rate_tuples.end(); iter++) {
795     ostringstream oss;
796     oss << "flow rate " << (*iter).first;
797     string flow_rate_str(oss.str());
798     string flow_rate_pop_size_str(flow_rate_str+" deme pop size");
799     string flow_rate_events_killed_str(flow_rate_str+" events killed");
800     string flow_rate_events_attempted_to_kill_str(flow_rate_str+" events attempted to kill");
801     string flow_rate_exe_ratio_str(flow_rate_str+" exe ratio");
802     string flow_rate_total_births_str(flow_rate_str+" total births");
803     string flow_rate_total_sleeping_str(flow_rate_str+" total sleeping");
804 
805     df.Write((*iter).first, flow_rate_str.c_str());
806     df.Write((*iter).second.orgCount.Average(), flow_rate_pop_size_str.c_str());
807     df.Write((*iter).second.eventsKilled.Average(), flow_rate_events_killed_str.c_str());
808     df.Write((*iter).second.attemptsToKillEvents.Average(), flow_rate_events_attempted_to_kill_str.c_str());
809     df.Write((*iter).second.AvgEnergyUsageRatio.Average(), flow_rate_exe_ratio_str.c_str());
810     df.Write((*iter).second.totalBirths.Average(), flow_rate_total_births_str.c_str());
811     df.Write((*iter).second.currentSleeping.Average(), flow_rate_total_sleeping_str.c_str());
812 
813   }
814   df.Endl();
815 
816   // reset all tuples
817   for(map<int, flow_rate_tuple >::iterator iter = flow_rate_tuples.begin(); iter != flow_rate_tuples.end(); iter++) {
818     (*iter).second.orgCount.Clear();
819     (*iter).second.eventsKilled.Clear();
820     (*iter).second.attemptsToKillEvents.Clear();
821     (*iter).second.AvgEnergyUsageRatio.Clear();
822     (*iter).second.totalBirths.Clear();
823     (*iter).second.currentSleeping.Clear();
824   }
825 }
826 
PrintErrorData(const cString & filename)827 void cStats::PrintErrorData(const cString& filename)
828 {
829   cDataFile& df = m_world->GetDataFile(filename);
830 
831   df.WriteComment("Avida Standard Error Data");
832   df.WriteTimeStamp();
833 
834   df.Write(m_update,                 "Update");
835   df.Write(sum_merit.StdError(),           "Merit");
836   df.Write(sum_gestation.StdError(),       "Gestation Time");
837   df.Write(sum_fitness.StdError(),         "Fitness");
838   df.Write(sum_repro_rate.StdError(),      "Repro Rate?");
839   df.Write(sum_size.StdError(),            "Size");
840   df.Write(sum_copy_size.StdError(),       "Copied Size");
841   df.Write(sum_exe_size.StdError(),        "Executed Size");
842   df.Write(sum_abundance.StdError(),       "Abundance");
843   df.Write(-1,                             "(No Data)");
844   df.Write(-1,                             "(No Data)");
845   df.Write(sum_genotype_depth.StdError(),  "Genotype Depth");
846   df.Write(sum_generation.StdError(),      "Generation");
847   df.Write(sum_neutral_metric.StdError(),  "Neutral Metric");
848   df.Write(sum_lineage_label.StdError(),   "Lineage Label");
849   df.Write(rave_true_replication_rate.StdError(), "True Replication Rate (based on births/update, time-averaged)");
850   df.Endl();
851 }
852 
853 
PrintVarianceData(const cString & filename)854 void cStats::PrintVarianceData(const cString& filename)
855 {
856   cDataFile& df = m_world->GetDataFile(filename);
857 
858   df.WriteComment("Avida Variance Data");
859   df.WriteTimeStamp();
860 
861   df.Write(m_update,                 "Update");
862   df.Write(sum_merit.Variance(),           "Merit");
863   df.Write(sum_gestation.Variance(),       "Gestation Time");
864   df.Write(sum_fitness.Variance(),         "Fitness");
865   df.Write(sum_repro_rate.Variance(),      "Repro Rate?");
866   df.Write(sum_size.Variance(),            "Size");
867   df.Write(sum_copy_size.Variance(),       "Copied Size");
868   df.Write(sum_exe_size.Variance(),        "Executed Size");
869   df.Write(sum_abundance.Variance(),       "Abundance");
870   df.Write(-1,                             "(No Data)");
871   df.Write(-1,                             "(No Data)");
872   df.Write(sum_genotype_depth.Variance(),  "Genotype Depth");
873   df.Write(sum_generation.Variance(),      "Generation");
874   df.Write(sum_neutral_metric.Variance(),  "Neutral Metric");
875   df.Write(sum_lineage_label.Variance(),   "Lineage Label");
876   df.Write(rave_true_replication_rate.Variance(), "True Replication Rate (based on births/update, time-averaged)");
877   df.Endl();
878 }
879 
880 
PrintDominantData(const cString & filename)881 void cStats::PrintDominantData(const cString& filename)
882 {
883   cDataFile& df = m_world->GetDataFile(filename);
884 
885   df.WriteComment("Avida Dominant Data");
886   df.WriteTimeStamp();
887 
888   df.Write(m_update,     "Update");
889   df.Write(dom_merit,       "Average Merit of the Dominant Genotype");
890   df.Write(dom_gestation,   "Average Gestation Time of the Dominant Genotype");
891   df.Write(dom_fitness,     "Average Fitness of the Dominant Genotype");
892   df.Write(dom_repro_rate,  "Repro Rate?");
893   df.Write(dom_size,        "Size of Dominant Genotype");
894   df.Write(dom_copied_size, "Copied Size of Dominant Genotype");
895   df.Write(dom_exe_size,    "Executed Size of Dominant Genotype");
896   df.Write(dom_abundance,   "Abundance of Dominant Genotype");
897   df.Write(dom_births,      "Number of Births");
898   df.Write(dom_breed_true,  "Number of Dominant Breed True?");
899   df.Write(dom_gene_depth,  "Dominant Gene Depth");
900   df.Write(dom_breed_in,    "Dominant Breed In");
901   df.Write(max_fitness,     "Max Fitness?");
902   df.Write(dom_genotype_id, "Genotype ID of Dominant Genotype");
903   df.Write(dom_name,        "Name of the Dominant Genotype");
904   df.Endl();
905 }
906 
PrintParasiteData(const cString & filename)907 void cStats::PrintParasiteData(const cString& filename)
908 {
909   cDataFile& df = m_world->GetDataFile(filename);
910 
911   df.WriteComment("Avida Dominant Parasite Data");
912   df.WriteTimeStamp();
913   df.Write(m_update, "Update");
914   df.Write(num_parasites, "Number of Extant Parasites");
915   df.Endl();
916 }
917 
PrintPreyAverageData(const cString & filename)918 void cStats::PrintPreyAverageData(const cString& filename)
919 {
920   cDataFile& df = m_world->GetDataFile(filename);
921 
922   df.WriteComment("Prey Average Data");
923   df.WriteTimeStamp();
924 
925   df.Write(m_update,                          "Update");
926   df.Write(sum_prey_fitness.Average(),        "Fitness");
927   df.Write(sum_prey_gestation.Average(),      "Gestation Time");
928   df.Write(sum_prey_merit.Average(),          "Merit");
929   df.Write(sum_prey_creature_age.Average(),   "Creature Age");
930   df.Write(sum_prey_generation.Average(),     "Generation");
931   df.Write(sum_prey_size.Average(),           "Genome Length");
932   df.Write(prey_entropy,                      "Total Prey Genotypic Entropy");
933 
934   df.Endl();
935 }
936 
PrintPredatorAverageData(const cString & filename)937 void cStats::PrintPredatorAverageData(const cString& filename)
938 {
939   cDataFile& df = m_world->GetDataFile(filename);
940 
941   df.WriteComment("Predator Average Data");
942   df.WriteTimeStamp();
943 
944   df.Write(m_update,                          "Update");
945   df.Write(sum_pred_fitness.Average(),        "Fitness");
946   df.Write(sum_pred_gestation.Average(),      "Gestation Time");
947   df.Write(sum_pred_merit.Average(),          "Merit");
948   df.Write(sum_pred_creature_age.Average(),   "Creature Age");
949   df.Write(sum_pred_generation.Average(),     "Generation");
950   df.Write(sum_pred_size.Average(),           "Genome Length");
951   df.Write(pred_entropy,                      "Total Predator Genotypic Entropy");
952 
953   df.Endl();
954 }
955 
PrintPreyErrorData(const cString & filename)956 void cStats::PrintPreyErrorData(const cString& filename)
957 {
958   cDataFile& df = m_world->GetDataFile(filename);
959 
960   df.WriteComment("Prey Standard Error Data");
961   df.WriteTimeStamp();
962 
963   df.Write(m_update,                            "Update");
964   df.Write(sum_prey_fitness.StdError(),         "Fitness");
965   df.Write(sum_prey_gestation.StdError(),       "Gestation Time");
966   df.Write(sum_prey_merit.StdError(),           "Merit");
967   df.Write(sum_prey_creature_age.StdError(),    "Creature Age");
968   df.Write(sum_prey_generation.StdError(),      "Generation");
969   df.Write(sum_prey_size.StdError(),            "Genome Length");
970 
971   df.Endl();
972 }
973 
PrintPredatorErrorData(const cString & filename)974 void cStats::PrintPredatorErrorData(const cString& filename)
975 {
976   cDataFile& df = m_world->GetDataFile(filename);
977 
978   df.WriteComment("Predator Standard Error Data");
979   df.WriteTimeStamp();
980 
981   df.Write(m_update,                            "Update");
982   df.Write(sum_pred_fitness.StdError(),         "Fitness");
983   df.Write(sum_pred_gestation.StdError(),       "Gestation Time");
984   df.Write(sum_pred_merit.StdError(),           "Merit");
985   df.Write(sum_pred_creature_age.StdError(),    "Creature Age");
986   df.Write(sum_pred_generation.StdError(),      "Generation");
987   df.Write(sum_pred_size.StdError(),            "Genome Length");
988 
989   df.Endl();
990 }
991 
PrintPreyVarianceData(const cString & filename)992 void cStats::PrintPreyVarianceData(const cString& filename)
993 {
994   cDataFile& df = m_world->GetDataFile(filename);
995 
996   df.WriteComment("Prey Variance Data");
997   df.WriteTimeStamp();
998 
999   df.Write(m_update,                            "Update");
1000   df.Write(sum_prey_fitness.Variance(),         "Fitness");
1001   df.Write(sum_prey_gestation.Variance(),       "Gestation Time");
1002   df.Write(sum_prey_merit.Variance(),           "Merit");
1003   df.Write(sum_prey_creature_age.Variance(),    "Creature Age");
1004   df.Write(sum_prey_generation.Variance(),      "Generation");
1005   df.Write(sum_prey_size.Variance(),            "Genome Length");
1006 
1007   df.Endl();
1008 }
1009 
PrintPredatorVarianceData(const cString & filename)1010 void cStats::PrintPredatorVarianceData(const cString& filename)
1011 {
1012   cDataFile& df = m_world->GetDataFile(filename);
1013 
1014   df.WriteComment("Predator Variance Data");
1015   df.WriteTimeStamp();
1016 
1017   df.Write(m_update,                            "Update");
1018   df.Write(sum_pred_fitness.Variance(),         "Fitness");
1019   df.Write(sum_pred_gestation.Variance(),       "Gestation Time");
1020   df.Write(sum_pred_merit.Variance(),           "Merit");
1021   df.Write(sum_pred_creature_age.Variance(),    "Creature Age");
1022   df.Write(sum_pred_generation.Variance(),      "Generation");
1023   df.Write(sum_pred_size.Variance(),            "Genome Length");
1024 
1025   df.Endl();
1026 }
1027 
PrintMinPreyFailedAttacks(const cString & filename)1028 void cStats::PrintMinPreyFailedAttacks(const cString& filename)
1029 {
1030   cDataFile& df = m_world->GetDataFile(filename);
1031 
1032   if (!df.HeaderDone()) {
1033     df.WriteComment("Updates of individual attack that failed due to MIN_PREY config setting");
1034     df.WriteTimeStamp();
1035     df.Endl();
1036   }
1037 
1038   tArray<int> failure_events = m_world->GetPopulation().GetMinPreyFailedAttacks();
1039   if (failure_events.GetSize() > 0) {
1040     for (int i = 0; i < failure_events.GetSize(); i++) {
1041       df.WriteAnonymous(failure_events[i]);
1042       df.Endl();
1043     }
1044     m_world->GetPopulation().ClearMinPreyFailedAttacks();
1045   }
1046 }
1047 
PrintPreyInstructionData(const cString & filename,const cString & inst_set)1048 void cStats::PrintPreyInstructionData(const cString& filename, const cString& inst_set)
1049 {
1050   cDataFile& df = m_world->GetDataFile(filename);
1051 
1052   df.WriteComment("Prey org instruction execution data");
1053   df.WriteTimeStamp();
1054 
1055   df.Write(m_update, "Update");
1056 
1057   for (int i = 0; i < m_is_prey_exe_inst_map[inst_set].GetSize(); i++) {
1058     df.Write(m_is_prey_exe_inst_map[inst_set][i].Sum(), m_is_inst_names_map[inst_set][i]);
1059   }
1060   df.Endl();
1061 }
1062 
PrintPredatorInstructionData(const cString & filename,const cString & inst_set)1063 void cStats::PrintPredatorInstructionData(const cString& filename, const cString& inst_set)
1064 {
1065   cDataFile& df = m_world->GetDataFile(filename);
1066 
1067   df.WriteComment("Predator org instruction execution data");
1068   df.WriteTimeStamp();
1069 
1070   df.Write(m_update, "Update");
1071 
1072   for (int i = 0; i < m_is_pred_exe_inst_map[inst_set].GetSize(); i++) {
1073     df.Write(m_is_pred_exe_inst_map[inst_set][i].Sum(), m_is_inst_names_map[inst_set][i]);
1074   }
1075   df.Endl();
1076 }
1077 
PrintStatsData(const cString & filename)1078 void cStats::PrintStatsData(const cString& filename)
1079 {
1080   const int genotype_change = num_genotypes - num_genotypes_last;
1081   const double log_ave_fid = (ave_fidelity > 0.0 && ave_fidelity != 1.0) ? -Log(ave_fidelity) : 0.0;
1082   const double log_dom_fid = (dom_fidelity > 0.0 && ave_fidelity != 1.0) ? -Log(dom_fidelity) : 0.0;
1083 
1084   cDataFile& df = m_world->GetDataFile(filename);
1085 
1086   df.WriteComment("Generic Statistics Data");
1087   df.WriteTimeStamp();
1088 
1089   df.Write(m_update,          "update");
1090   df.Write(energy,               "average inferiority (energy)");
1091   df.Write(1.0 - ave_fidelity,   "ave probability of any mutations in genome");
1092   df.Write(1.0 - dom_fidelity,   "probability of any mutations in dom genome");
1093   df.Write(log_ave_fid,          "log(average fidelity)");
1094   df.Write(log_dom_fid,          "log(dominant fidelity)");
1095   df.Write(genotype_change,      "change in number of genotypes");
1096   df.Write(entropy,              "genotypic entropy");
1097   df.Write(species_entropy,      "species entropy");
1098   df.Write(coal_depth,           "depth of most reacent coalescence");
1099   df.Write(num_resamplings,      "Total number of resamplings this generation");
1100   df.Write(num_failedResamplings, "Total number of organisms that failed to resample this generation");
1101 
1102   df.Endl();
1103 }
1104 
1105 
PrintCountData(const cString & filename)1106 void cStats::PrintCountData(const cString& filename)
1107 {
1108   cDataFile& df = m_world->GetDataFile(filename);
1109 
1110   df.WriteComment("Avida count data");
1111   df.WriteTimeStamp();
1112 
1113   df.Write(m_update,         "update");
1114   df.Write(num_executed,           "number of insts executed this update");
1115   df.Write(num_creatures,          "number of organisms");
1116   df.Write(num_genotypes,          "number of different genotypes");
1117   df.Write(num_threshold,          "number of different threshold genotypes");
1118   df.Write(0,                      "number of different species");
1119   df.Write(0,                      "number of different threshold species");
1120   df.Write(num_lineages,           "number of different lineages");
1121   df.Write(num_births,             "number of births in this update");
1122   df.Write(num_deaths,             "number of deaths in this update");
1123   df.Write(num_breed_true,         "number of breed true");
1124   df.Write(num_breed_true_creatures, "number of breed true organisms?");
1125   df.Write(num_no_birth_creatures,   "number of no-birth organisms");
1126   df.Write(num_single_thread_creatures, "number of single-threaded organisms");
1127   df.Write(num_multi_thread_creatures, "number of multi-threaded organisms");
1128   df.Write(num_modified, "number of modified organisms");
1129   df.Endl();
1130 }
1131 
PrintMessageData(const cString & filename)1132 void cStats::PrintMessageData(const cString& filename) {
1133 	cDataFile& df = m_world->GetDataFile(filename);
1134 
1135   df.WriteComment( "Number of organism to organism messages\n" );
1136 
1137   df.Write( GetUpdate(), "update" );
1138 
1139   cPopulation& pop = m_world->GetPopulation();
1140   int numDemes = pop.GetNumDemes();
1141 
1142 	unsigned int totalMessagesSuccessfullySent(0);
1143 	unsigned int totalMessagesDropped(0);
1144 	unsigned int totalMessagesFailed(0);
1145 
1146 	for( int i=0; i < numDemes; i++ ){
1147 		totalMessagesSuccessfullySent += pop.GetDeme(i).GetMessageSuccessfullySent();
1148 		totalMessagesDropped += pop.GetDeme(i).GetMessageDropped();
1149 		totalMessagesFailed  += pop.GetDeme(i).GetMessageSendFailed();
1150 	}
1151 
1152 	df.Write(totalMessagesSuccessfullySent, "Sent successfully");
1153 	df.Write(totalMessagesDropped, "Dropped");
1154 	df.Write(totalMessagesFailed, "Failed");
1155 
1156   df.Endl();
1157 }
1158 
PrintInterruptData(const cString & filename)1159 void cStats::PrintInterruptData(const cString& filename) {
1160 	cDataFile& df = m_world->GetDataFile(filename);
1161 
1162   df.WriteComment( "Total number of organisms interrupted\n" );
1163 
1164   df.Write( GetUpdate(), "update" );
1165 
1166   cPopulation& pop = m_world->GetPopulation();
1167   int numDemes = pop.GetNumDemes();
1168 
1169 	unsigned int totalOrgsInterrupted(0);
1170   unsigned int totalThreads(0);
1171 	const int NUM_INTERRUPT_MSG_TYPES = 10;
1172   int interruptTypeCounts[NUM_INTERRUPT_MSG_TYPES] = {0};
1173 
1174 	for( int i = 0; i < numDemes; ++i ){
1175     const cDeme & cur_deme = m_world->GetPopulation().GetDeme(i);
1176     for (int j = 0; j < cur_deme.GetSize(); ++j) {
1177       cPopulationCell& cur_cell = cur_deme.GetCell(j);
1178       cOrganism* org = cur_cell.GetOrganism();
1179       if (cur_cell.IsOccupied() == false) {
1180         continue;
1181       } else if (org->IsInterrupted()) {
1182         ++totalOrgsInterrupted;
1183         int numThreadsInOrg = org->GetHardware().GetNumThreads();
1184         totalThreads += numThreadsInOrg;
1185         for(int k = 0; k< numThreadsInOrg; ++k) {
1186           ++interruptTypeCounts[org->GetHardware().GetThreadMessageTriggerType(k)];
1187         }
1188       }
1189     }
1190   }
1191 
1192 	df.Write(totalOrgsInterrupted, "Total organisms interrupted");
1193 	df.Write(totalThreads, "Total threads");
1194   for (int i = 0; i < NUM_INTERRUPT_MSG_TYPES; ++i) {
1195     df.Write(interruptTypeCounts[i], "Interrupt Counts");
1196   }
1197   df.Endl();
1198 }
1199 
PrintTotalsData(const cString & filename)1200 void cStats::PrintTotalsData(const cString& filename)
1201 {
1202   cDataFile& df = m_world->GetDataFile(filename);
1203   df.Write(m_update, "Update");
1204   df.Write((tot_executed+num_executed), "Total Instructions Executed");
1205   df.Write(num_executed, "Instructions Executed This Update");
1206   df.Write(tot_organisms, "Total Organisms");
1207   df.Write(tot_genotypes, "Total Genotypes");
1208   df.Write(tot_threshold, "Total Threshold");
1209   df.Write(0, "Total Species");
1210   df.Write(tot_lineages, "Total Lineages");
1211   df.Endl();
1212 }
1213 
PrintThreadsData(const cString & filename)1214 void cStats::PrintThreadsData(const cString& filename)
1215 {
1216   cDataFile& df = m_world->GetDataFile(filename);
1217   df.Write(m_update, "Update");
1218   df.Write(tot_organisms, "Total Organisms");
1219   df.Write(m_world->GetPopulation().GetLiveOrgList().GetSize(), "Total Living Organisms");
1220   df.Write(m_num_threads, "Total Living Org Threads");
1221   df.Endl();
1222 }
1223 
1224 
1225 
PrintTasksData(const cString & filename)1226 void cStats::PrintTasksData(const cString& filename)
1227 {
1228 	cString file = filename;
1229 
1230 	// flag to print both tasks.dat and taskquality.dat
1231 	if (filename == "tasksq.dat")
1232 	{
1233 		file = "tasks.dat";
1234 		PrintTasksQualData("taskquality.dat");
1235 	}
1236 
1237 	// print tasks.dat
1238 	cDataFile& df = m_world->GetDataFile(file);
1239 	df.WriteComment("Avida tasks data");
1240 	df.WriteTimeStamp();
1241 	df.WriteComment("First column gives the current update, next columns give the number");
1242 	df.WriteComment("of organisms that have the particular task as a component of their merit");
1243 
1244 	df.Write(m_update,   "Update");
1245 	for(int i = 0; i < task_last_count.GetSize(); i++) {
1246 		df.Write(task_last_count[i], task_names[i] );
1247 	}
1248 	df.Endl();
1249 }
1250 
PrintHostTasksData(const cString & filename)1251 void cStats::PrintHostTasksData(const cString& filename)
1252 {
1253 	cString file = filename;
1254 
1255 	// flag to print both tasks.dat and taskquality.dat
1256 	if (filename == "tasksq.dat")
1257 	{
1258 		file = "host_tasks.dat";
1259 	}
1260 
1261 	// print tasks.dat
1262 	cDataFile& df = m_world->GetDataFile(file);
1263 	df.WriteComment("Avida Host Tasks data");
1264 	df.WriteTimeStamp();
1265 	df.WriteComment("First column gives the current update, next columns give the number");
1266 	df.WriteComment("of Hosts that have the particular task");
1267 
1268 	df.Write(m_update,   "Update");
1269 	for(int i = 0; i < tasks_host_last.GetSize(); i++) {
1270 		df.Write(tasks_host_last[i], task_names[i] );
1271 	}
1272 	df.Endl();
1273 }
1274 
PrintParasiteTasksData(const cString & filename)1275 void cStats::PrintParasiteTasksData(const cString& filename)
1276 {
1277 	cString file = filename;
1278 
1279 	// flag to print both tasks.dat and taskquality.dat
1280 	if (filename == "tasksq.dat")
1281 	{
1282 		file = "parasite_tasks.dat";
1283 	}
1284 
1285 	// print tasks.dat
1286 	cDataFile& df = m_world->GetDataFile(file);
1287 	df.WriteComment("Avida tasks data");
1288 	df.WriteTimeStamp();
1289 	df.WriteComment("First column gives the current update, next columns give the number");
1290 	df.WriteComment("of Parasites that have the particular task");
1291 
1292 	df.Write(m_update,   "Update");
1293 	for(int i = 0; i < tasks_parasite_last.GetSize(); i++) {
1294 		df.Write(tasks_parasite_last[i], task_names[i] );
1295 	}
1296 	df.Endl();
1297 }
1298 
1299 
PrintTasksExeData(const cString & filename)1300 void cStats::PrintTasksExeData(const cString& filename)
1301 {
1302   cDataFile& df = m_world->GetDataFile(filename);
1303 
1304   df.WriteComment("Avida tasks execution data");
1305   df.WriteTimeStamp();
1306   df.WriteComment("First column gives the current update, all further columns give the number");
1307   df.WriteComment("of times the particular task has been executed this update.");
1308 
1309   df.Write(m_update,   "Update");
1310   for (int i = 0; i < task_exe_count.GetSize(); i++) {
1311     df.Write(task_exe_count[i], task_names[i] );
1312   }
1313   df.Endl();
1314 }
1315 
PrintTasksQualData(const cString & filename)1316 void cStats::PrintTasksQualData(const cString& filename)
1317 {
1318   cDataFile& df = m_world->GetDataFile(filename);
1319 
1320   df.WriteComment("Avida tasks quality data");
1321   df.WriteTimeStamp();
1322   df.WriteComment("First column gives the current update, rest give average and max task quality");
1323   df.Write(m_update, "Update");
1324   for(int i = 0; i < task_last_count.GetSize(); i++) {
1325     double qual = 0.0;
1326     if (task_last_count[i] > 0)
1327       qual = task_last_quality[i] / static_cast<double>(task_last_count[i]);
1328     df.Write(qual, task_names[i] + " Average");
1329     df.Write(task_last_max_quality[i], task_names[i] + " Max");
1330   }
1331   df.Endl();
1332 }
1333 
PrintNewTasksData(const cString & filename)1334 void cStats::PrintNewTasksData(const cString& filename)
1335 {
1336   cDataFile& df = m_world->GetDataFile(filename);
1337 
1338   df.WriteComment("Avida new tasks data");
1339   df.WriteTimeStamp();
1340   df.WriteComment("First column gives the current update, all further columns give the number");
1341   df.WriteComment("of times the particular task has newly evolved since the last time printed.");
1342 
1343   df.Write(m_update,   "Update");
1344   for (int i = 0; i < new_task_count.GetSize(); i++) {
1345     df.Write(new_task_count[i], task_names[i]);
1346   }
1347   df.Endl();
1348   new_task_count.SetAll(0);
1349 }
1350 
PrintNewTasksDataPlus(const cString & filename)1351 void cStats::PrintNewTasksDataPlus(const cString& filename)
1352 {
1353   cDataFile& df = m_world->GetDataFile(filename);
1354 
1355   df.WriteComment("Avida new tasks data");
1356   df.WriteTimeStamp();
1357   df.WriteComment("First column gives the current update, all further columns are in sets of 3, giving the number");
1358   df.WriteComment("of times the particular task has newly evolved since the last time printed, then the average");
1359   df.WriteComment("number of tasks the parent of the organism evolving the new task performed, then the average");
1360   df.WriteComment("number of tasks the organism evolving the new task performed.  One set of 3 for each task");
1361 
1362   df.Write(m_update,   "Update");
1363   for (int i = 0; i < new_task_count.GetSize(); i++) {
1364     df.Write(new_task_count[i], task_names[i] + " - num times newly evolved");
1365 	double prev_ave = -1;
1366 	double cur_ave = -1;
1367 	if (new_task_count[i]>0) {
1368 		prev_ave = prev_task_count[i]/double(new_task_count[i]);
1369 		cur_ave = cur_task_count[i]/double(new_task_count[i]);
1370 	}
1371 	df.Write(prev_ave, "ave num tasks parent performed");
1372 	df.Write(cur_ave, "ave num tasks cur org performed");
1373 
1374   }
1375   df.Endl();
1376   new_task_count.SetAll(0);
1377   prev_task_count.SetAll(0);
1378   cur_task_count.SetAll(0);
1379 }
1380 
PrintNewReactionData(const cString & filename)1381 void cStats::PrintNewReactionData(const cString& filename)
1382 {
1383   cDataFile& df = m_world->GetDataFile(filename);
1384 
1385   df.WriteComment("Avida new reactions data");
1386   df.WriteTimeStamp();
1387   df.WriteComment("First column gives the current update, all further columns give the number");
1388   df.WriteComment("of times the particular reaction has newly evolved since the last time printed.");
1389 
1390   df.Write(m_update,   "Update");
1391   for (int i = 0; i < new_reaction_count.GetSize(); i++) {
1392     df.Write(new_reaction_count[i], reaction_names[i]);
1393   }
1394   df.Endl();
1395   new_reaction_count.SetAll(0);
1396 }
1397 
PrintDynamicMaxMinData(const cString & filename)1398 void cStats::PrintDynamicMaxMinData(const cString& filename)
1399 {
1400 	cDataFile& df = m_world->GetDataFile(filename);
1401 
1402 	df.WriteComment("Avida dynamic max min data");
1403 	df.WriteTimeStamp();
1404 	df.WriteComment("First column gives the current update, 2nd and 3rd give max and min Fx");
1405 	df.Write(m_update, "Update");
1406 	for(int i = 0; i < task_last_count.GetSize(); i++) {
1407 		double max = m_world->GetEnvironment().GetTask(i).GetArguments().GetDouble(1);
1408 		double min = m_world->GetEnvironment().GetTask(i).GetArguments().GetDouble(2);
1409 		df.Write(max, task_names[i] + " Max");
1410 		df.Write(min, task_names[i] + " Min");
1411 	}
1412 	df.Endl();
1413 }
1414 
PrintReactionData(const cString & filename)1415 void cStats::PrintReactionData(const cString& filename)
1416 {
1417   cDataFile& df = m_world->GetDataFile(filename);
1418 
1419   df.WriteComment("Avida reaction data");
1420   df.WriteTimeStamp();
1421   df.WriteComment("First column gives the current update, all further columns give the number");
1422   df.WriteComment("of currently living organisms each reaction has affected.");
1423 
1424 	df.Write(m_update,   "Update");
1425 	for(int i = 0; i < m_reaction_last_count.GetSize(); i++) {
1426 		df.Write(m_reaction_last_count[i], reaction_names[i]);
1427 	}
1428 	df.Endl();
1429 }
1430 
PrintCurrentReactionData(const cString & filename)1431 void cStats::PrintCurrentReactionData(const cString& filename)
1432 {
1433   cDataFile& df = m_world->GetDataFile(filename);
1434 
1435   df.WriteComment("Avida reaction data");
1436   df.WriteTimeStamp();
1437   df.WriteComment("First column gives the current update, all further columns give the number");
1438   df.WriteComment("of currently living organisms each reaction has affected.");
1439 
1440 	df.Write(m_update,   "Update");
1441 	for(int i = 0; i < m_reaction_cur_count.GetSize(); i++) {
1442 		df.Write(m_reaction_cur_count[i], reaction_names[i]);
1443 	}
1444 	df.Endl();
1445 }
1446 
1447 
PrintReactionRewardData(const cString & filename)1448 void cStats::PrintReactionRewardData(const cString& filename)
1449 {
1450   cDataFile& df = m_world->GetDataFile(filename);
1451 
1452   df.WriteComment("Avida reaction data");
1453   df.WriteTimeStamp();
1454   df.WriteComment("First column gives the current update, all further columns give the add bonus reward");
1455   df.WriteComment("currently living organisms have garnered from each reaction.");
1456 
1457   df.Write(m_update,   "Update");
1458   for (int i = 0; i < m_reaction_last_add_reward.GetSize(); i++) {
1459     df.Write(m_reaction_last_add_reward[i], reaction_names[i]);
1460   }
1461   df.Endl();
1462 }
1463 
1464 
PrintCurrentReactionRewardData(const cString & filename)1465 void cStats::PrintCurrentReactionRewardData(const cString& filename)
1466 {
1467   cDataFile& df = m_world->GetDataFile(filename);
1468 
1469   df.WriteComment("Avida reaction data");
1470   df.WriteTimeStamp();
1471   df.WriteComment("First column gives the current update, all further columns give the add bonus reward");
1472   df.WriteComment("currently living organisms have garnered from each reaction.");
1473 
1474   df.Write(m_update,   "Update");
1475   for (int i = 0; i < m_reaction_cur_add_reward.GetSize(); i++) {
1476     df.Write(m_reaction_cur_add_reward[i], reaction_names[i]);
1477   }
1478   df.Endl();
1479 }
1480 
1481 
PrintReactionExeData(const cString & filename)1482 void cStats::PrintReactionExeData(const cString& filename)
1483 {
1484   cDataFile& df = m_world->GetDataFile(filename);
1485 
1486   df.WriteComment("Avida reaction execution data");
1487   df.WriteTimeStamp();
1488   df.WriteComment("First column gives the current update, all further columns give the number");
1489   df.WriteComment("of times the particular reaction has been triggered this update.");
1490 
1491   df.Write(m_update,   "Update");
1492   for (int i = 0; i < m_reaction_exe_count.GetSize(); i++) {
1493     df.Write(m_reaction_exe_count[i], reaction_names[i]);
1494   }
1495   df.Endl();
1496 }
1497 
1498 
PrintResourceData(const cString & filename)1499 void cStats::PrintResourceData(const cString& filename)
1500 {
1501   cDataFile& df = m_world->GetDataFile(filename);
1502 
1503   df.WriteComment("Avida resource data");
1504   df.WriteTimeStamp();
1505   df.WriteComment("First column gives the current update, all further columns give the quantity");
1506   df.WriteComment("of the particular resource at that update.");
1507 
1508   df.Write(m_update,   "Update");
1509 
1510   // Check for spatial resources if they exist total up the resource in each
1511   // cell and print that total.  Also call the routine to print the individual
1512   // maps for each spatial resource
1513 
1514   for (int i = 0; i < resource_count.GetSize(); i++) {
1515    if (resource_geometry[i] != nGeometry::GLOBAL && resource_geometry[i] != nGeometry::PARTIAL) {
1516          double sum_spa_resource = 0;
1517       for (int j = 0; j < spatial_res_count[i].GetSize(); j++) {
1518          sum_spa_resource += spatial_res_count[i][j];
1519       }
1520       df.Write(sum_spa_resource, resource_names[i] );
1521       PrintSpatialResData(filename, i);
1522     } else {
1523       df.Write(resource_count[i], resource_names[i] );
1524     }
1525   }
1526   df.Endl();
1527 }
1528 
PrintResourceLocData(const cString & filename,cAvidaContext & ctx)1529 void cStats::PrintResourceLocData(const cString& filename, cAvidaContext& ctx)
1530 {
1531   cDataFile& df = m_world->GetDataFile(filename);
1532 
1533   df.WriteComment("Avida resource location data");
1534   df.WriteTimeStamp();
1535   df.WriteComment("First column gives the current update, all further columns give the cell id");
1536   df.WriteComment("for center of gradient resources at that update.");
1537 
1538   df.Write(m_update,   "Update");
1539 
1540   const cResourceLib& resLib = m_world->GetEnvironment().GetResourceLib();
1541   for (int i = 0; i < resLib.GetSize(); i++) {
1542     if (resLib.GetResource(i)->GetGradient()) {
1543       df.Write(m_world->GetPopulation().GetCurrPeakX(ctx, i) + (m_world->GetPopulation().GetCurrPeakY(ctx, i) * m_world->GetConfig().WORLD_X.Get()), "CellID");
1544     }
1545   }
1546   df.Endl();
1547 }
1548 
PrintResWallLocData(const cString & filename,cAvidaContext & ctx)1549 void cStats::PrintResWallLocData(const cString& filename, cAvidaContext& ctx)
1550 {
1551   cDataFile& df = m_world->GetDataFile(filename);
1552 
1553   if (!df.HeaderDone()) {
1554     df.WriteComment("Avida wall resource filled cells data");
1555     df.WriteTimeStamp();
1556     df.WriteComment("First column gives the current update, all further columns give filled cell ids for each wall res");
1557     df.Endl();
1558   }
1559 
1560   std::ofstream& fp = df.GetOFStream();
1561   fp << m_update << " ";
1562 
1563   const cResourceLib& resLib = m_world->GetEnvironment().GetResourceLib();
1564   for (int i = 0; i < resLib.GetSize(); i++) {
1565     if (resLib.GetResource(i)->GetGradient() && resLib.GetResource(i)->GetHabitat() == 2) {
1566       tArray<int>& cells = *(m_world->GetPopulation().GetWallCells(i));
1567       for (int i = 0; i < cells.GetSize() - 1; i++) {
1568         fp << cells[i] << ",";
1569       }
1570       fp << cells[cells.GetSize() - 1] << " ";
1571     }
1572   }
1573   fp << endl;
1574 }
1575 
PrintSpatialResData(const cString & filename,int i)1576 void cStats::PrintSpatialResData(const cString& filename, int i)
1577 {
1578 
1579   // Write spatial resource data to a file that can easily be read into Matlab
1580 
1581   cString tmpfilename = "resource_";
1582   tmpfilename +=  resource_names[i] + ".m";
1583   cDataFile& df = m_world->GetDataFile(tmpfilename);
1584   cString UpdateStr = resource_names[i] +
1585                       cStringUtil::Stringf( "%07i", GetUpdate() ) + " = [ ...";
1586 
1587   df.WriteRaw(UpdateStr);
1588 
1589   int gridsize = spatial_res_count[i].GetSize();
1590   int xsize = m_world->GetConfig().WORLD_X.Get();
1591 
1592   // write grid to file
1593 
1594   for (int j = 0; j < gridsize; j++) {
1595     df.WriteBlockElement(spatial_res_count[i][j], j, xsize);
1596   }
1597   df.WriteRaw("];");
1598   df.Flush();
1599 }
1600 
1601 // @WRE: Added method for printing out visit data
PrintCellVisitsData(const cString & filename)1602 void cStats::PrintCellVisitsData(const cString& filename)
1603 {
1604   // Write cell visits data to a file that can easily be read into Matlab
1605 
1606   cString tmpfilename = "visits.m";
1607   cDataFile& df = m_world->GetDataFile(tmpfilename);
1608   cString UpdateStr = cStringUtil::Stringf( "visits%07i", GetUpdate() ) + " = [ ...";
1609 
1610   df.WriteRaw(UpdateStr);
1611 
1612   int xsize = m_world->GetConfig().WORLD_X.Get();
1613 
1614   for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
1615     df.WriteBlockElement(m_world->GetPopulation().GetCell(i).GetVisits(), i, xsize);
1616   }
1617 
1618   df.WriteRaw("];");
1619   df.Flush();
1620 }
1621 
1622 
PrintTimeData(const cString & filename)1623 void cStats::PrintTimeData(const cString& filename)
1624 {
1625   cDataFile& df = m_world->GetDataFile(filename);
1626 
1627   df.WriteComment("Avida time data");
1628   df.WriteTimeStamp();
1629 
1630   df.Write(m_update,              "update");
1631   df.Write(avida_time,               "avida time");
1632   df.Write(sum_generation.Average(), "average generation");
1633   df.Write(num_executed,             "num_executed?");
1634   df.Endl();
1635 }
1636 
1637 
1638 //@MRR Add additional time information
PrintExtendedTimeData(const cString & filename)1639 void cStats::PrintExtendedTimeData(const cString& filename)
1640 {
1641 	cDataFile& df = m_world->GetDataFile(filename);
1642 	df.WriteTimeStamp();
1643 	df.Write(m_update, "update");
1644 	df.Write(avida_time, "avida time");
1645 	df.Write(num_executed, "num_executed");
1646 	df.Write(tot_organisms, "num_organisms");
1647 	df.Endl();
1648 }
1649 
PrintMutationRateData(const cString & filename)1650 void cStats::PrintMutationRateData(const cString& filename)
1651 {
1652   cDataFile& df = m_world->GetDataFile(filename);
1653 
1654   df.WriteComment("Avida copy mutation rate data");
1655   df.WriteTimeStamp();
1656 
1657   df.Write(m_update, "Update");
1658   df.Write(sum_copy_mut_rate.Mean(), "Average copy mutation rate");
1659   df.Write(sum_copy_mut_rate.Variance(), "Variance in copy mutation rate");
1660   df.Write(sum_copy_mut_rate.StdDeviation(), "Standard Deviation in copy mutation rate");
1661   df.Write(sum_copy_mut_rate.Skewness(), "Skew in copy mutation rate");
1662   df.Write(sum_copy_mut_rate.Kurtosis(), "Kurtosis in copy mutation rate");
1663 
1664   df.Write(sum_log_copy_mut_rate.Mean(), "Average log(copy mutation rate)");
1665   df.Write(sum_log_copy_mut_rate.Variance(), "Variance in log(copy mutation rate)");
1666   df.Write(sum_log_copy_mut_rate.StdDeviation(), "Standard Deviation in log(copy mutation rate)");
1667   df.Write(sum_log_copy_mut_rate.Skewness(), "Skew in log(copy mutation rate)");
1668   df.Write(sum_log_copy_mut_rate.Kurtosis(), "Kurtosis in log(copy mutation rate)");
1669   df.Endl();
1670 
1671 }
1672 
1673 
PrintDivideMutData(const cString & filename)1674 void cStats::PrintDivideMutData(const cString& filename)
1675 {
1676   cDataFile& df = m_world->GetDataFile(filename);
1677 
1678   df.WriteComment("Avida divide mutation rate data");
1679   df.WriteTimeStamp();
1680 
1681   df.Write(m_update, "Update");
1682   df.Write(sum_div_mut_rate.Mean(), "Average divide mutation rate");
1683   df.Write(sum_div_mut_rate.Variance(), "Variance in divide mutation rate");
1684   df.Write(sum_div_mut_rate.StdDeviation(), "Standard Deviation in divide mutation rate");
1685   df.Write(sum_div_mut_rate.Skewness(), "Skew in divide mutation rate");
1686   df.Write(sum_div_mut_rate.Kurtosis(), "Kurtosis in divide mutation rate");
1687 
1688   df.Write(sum_log_div_mut_rate.Mean(), "Average log(divide mutation rate)");
1689   df.Write(sum_log_div_mut_rate.Variance(), "Variance in log(divide mutation rate)");
1690   df.Write(sum_log_div_mut_rate.StdDeviation(), "Standard Deviation in log(divide mutation rate)");
1691   df.Write(sum_log_div_mut_rate.Skewness(), "Skew in log(divide mutation rate)");
1692   df.Write(sum_log_div_mut_rate.Kurtosis(), "Kurtosis in log(divide mutation rate)");
1693   df.Endl();
1694 }
1695 
PrintInstructionData(const cString & filename,const cString & inst_set)1696 void cStats::PrintInstructionData(const cString& filename, const cString& inst_set)
1697 {
1698   cDataFile& df = m_world->GetDataFile(filename);
1699 
1700   df.WriteComment("Avida instruction execution data");
1701   df.WriteTimeStamp();
1702 
1703   df.Write(m_update, "Update");
1704 
1705   for (int i = 0; i < m_is_exe_inst_map[inst_set].GetSize(); i++) {
1706     df.Write(m_is_exe_inst_map[inst_set][i].Sum(), m_is_inst_names_map[inst_set][i]);
1707   }
1708 
1709   df.Endl();
1710 }
1711 
PrintMarketData(const cString & filename)1712 void cStats::PrintMarketData(const cString& filename)
1713 {
1714 	cDataFile& df = m_world->GetDataFile(filename);
1715 
1716 	df.WriteComment( "Avida market data\n" );
1717 	df.WriteComment("cumulative totals since the last update data was printed" );
1718 	df.WriteTimeStamp();
1719 	df.Write( GetUpdate(), "update" );
1720 	df.Write( num_bought, "num bought" );
1721 	df.Write( num_sold, "num sold" );
1722 	df.Write(num_used, "num used" );
1723 	df.Write(num_own_used, "num own used" );
1724 	num_bought = num_sold = num_used = num_own_used = 0;
1725   df.Endl();
1726 }
1727 
PrintSenseData(const cString & filename)1728 void cStats::PrintSenseData(const cString& filename)
1729 {
1730   cDataFile& df = m_world->GetDataFile(filename);
1731 
1732   df.WriteComment( "Avida sense instruction usage\n" );
1733   df.WriteComment("total number of organisms whose parents executed sense instructions with given labels" );
1734 
1735   df.Write( GetUpdate(), "update" );
1736 
1737   for( int i=0; i < sense_last_count.GetSize(); i++ ){
1738     df.Write(sense_last_count[i], sense_names[i]);
1739   }
1740   df.Endl();
1741 }
1742 
PrintSenseExeData(const cString & filename)1743 void cStats::PrintSenseExeData(const cString& filename)
1744 {
1745   cDataFile& df = m_world->GetDataFile(filename);
1746 
1747   df.WriteComment( "Avida sense instruction usage\n" );
1748   df.WriteComment("total number of sense instructions executed by the parents of current organisms with given labels" );
1749 
1750   df.Write( GetUpdate(), "update" );
1751 
1752   for( int i=0; i < sense_last_exe_count.GetSize(); i++ ){
1753     df.Write(sense_last_exe_count[i], sense_names[i]);
1754   }
1755   df.Endl();
1756 }
1757 
PrintInternalTasksData(const cString & filename)1758 void cStats::PrintInternalTasksData(const cString& filename)
1759 {
1760 	cString file = filename;
1761 
1762 	// flag to print both in_tasks.dat and in_taskquality.dat
1763 	if (filename == "in_tasksq.dat")
1764 	{
1765 		file = "in_tasks.dat";
1766 		PrintInternalTasksQualData("in_taskquality.dat");
1767 	}
1768 
1769 	// print in_tasks.dat
1770 	cDataFile& df = m_world->GetDataFile(file);
1771 	df.WriteComment("Avida tasks data: tasks performed with internal resources");
1772 	df.WriteTimeStamp();
1773 	df.WriteComment("First column gives the current update, next columns give the number");
1774 	df.WriteComment("of organisms that have the particular task, performed with internal resources, ");
1775 	df.WriteComment("as a component of their merit");
1776 
1777 	df.Write(m_update,   "Update");
1778 	for(int i = 0; i < task_internal_last_count.GetSize(); i++) {
1779 		df.Write(task_internal_last_count[i], task_names[i] );
1780 	}
1781 	df.Endl();
1782 }
1783 
PrintInternalTasksQualData(const cString & filename)1784 void cStats::PrintInternalTasksQualData(const cString& filename)
1785 {
1786   cDataFile& df = m_world->GetDataFile(filename);
1787 
1788   df.WriteComment("Avida tasks quality data: tasks performed using internal resources");
1789   df.WriteTimeStamp();
1790   df.WriteComment("First column gives the current update, rest give average and max task quality ");
1791   df.WriteComment("for those tasks performed using internal resources");
1792   df.Write(m_update, "Update");
1793   for(int i = 0; i < task_internal_last_count.GetSize(); i++) {
1794     double qual = 0.0;
1795     if (task_internal_last_count[i] > 0)
1796       qual = task_internal_last_quality[i] / static_cast<double>(task_internal_last_count[i]);
1797     df.Write(qual, task_names[i] + " Average");
1798     df.Write(task_internal_last_max_quality[i], task_names[i] + " Max");
1799   }
1800   df.Endl();
1801 }
1802 
PrintSleepData(const cString & filename)1803 void cStats::PrintSleepData(const cString& filename){
1804   cDataFile& df = m_world->GetDataFile(filename);
1805 
1806   df.WriteComment( "Number of organisms sleeping\n" );
1807   df.WriteComment("total number of organisms sleeping" );
1808 
1809   df.Write( GetUpdate(), "update" );
1810 
1811   cPopulation& pop = m_world->GetPopulation();
1812   int numDemes = pop.GetNumDemes();
1813 
1814   for( int i=0; i < numDemes; i++ ){
1815     df.Write(pop.GetDeme(i).GetSleepingCount(), cStringUtil::Stringf("DemeID %d", i));
1816   }
1817   df.Endl();
1818 }
1819 
PrintCompetitionData(const cString & filename)1820 void cStats::PrintCompetitionData(const cString& filename){
1821   cDataFile& df = m_world->GetDataFile(filename);
1822 
1823   df.WriteComment( "Competition results\n" );
1824   df.WriteComment( "results of the current competitions" );
1825 
1826   df.Write( GetUpdate(), "update" );
1827   df.Write( avg_competition_fitness, "average competition fitness" );
1828   df.Write( min_competition_fitness, "min competition fitness" );
1829   df.Write( max_competition_fitness, "max competition fitness" );
1830   df.Write( avg_competition_copied_fitness, "average copied fitness" );
1831   df.Write( min_competition_copied_fitness, "min copied fitness" );
1832   df.Write( max_competition_copied_fitness, "max copied fitness" );
1833   df.Write( num_orgs_replicated, "number of organisms copied" );
1834 
1835   // Only print trial info if there were multiple trials.
1836   if (avg_trial_fitnesses.GetSize() > 1)
1837   {
1838     for( int i=0; i < avg_trial_fitnesses.GetSize(); i++ ){
1839       df.Write(avg_trial_fitnesses[i], cStringUtil::Stringf("trial.%d fitness", i));
1840     }
1841   }
1842   df.Endl();
1843 }
1844 
1845 
1846 /*! This method is called whenever an organism successfully sends a message.  Success,
1847 in this case, means that the message has been delivered to the receive buffer of
1848 the organism that this message was sent to. */
SentMessage(const cOrgMessage & msg)1849 void cStats::SentMessage(const cOrgMessage& msg)
1850 {
1851   // Check to see if this message matches any of our predicates.
1852   for(message_pred_ptr_list::iterator i=m_message_predicates.begin(); i!=m_message_predicates.end(); ++i) {
1853     (**i)(msg); // Predicate is responsible for tracking info about messages.
1854   }
1855 }
1856 
1857 
1858 /*! This method adds a message predicate to the list of all predicates.  Each predicate
1859 in the list is evaluated for every sent message.
1860 
1861 NOTE: cStats does NOT own the predicate pointer!  (It DOES NOT delete them!)
1862 */
AddMessagePredicate(cOrgMessagePredicate * predicate)1863 void cStats::AddMessagePredicate(cOrgMessagePredicate* predicate)
1864 {
1865   m_message_predicates.push_back(predicate);
1866 }
1867 
RemoveMessagePredicate(cOrgMessagePredicate * predicate)1868 void cStats::RemoveMessagePredicate(cOrgMessagePredicate* predicate)
1869 {
1870   for(message_pred_ptr_list::iterator iter = m_message_predicates.begin(); iter != m_message_predicates.end(); iter++) {
1871     if((*iter) == predicate) {
1872       m_message_predicates.erase(iter);
1873       return;
1874     }
1875   }
1876 }
1877 
1878 
1879 /*! This method adds a movement predicate to the list of all movement predicates.  Each predicate
1880  * in the list is evaluated for every organism movement.
1881  *
1882  * NOTE: cStats does NOT own the predicate pointer!  (It DOES NOT delete them!)
1883  * */
AddMovementPredicate(cOrgMovementPredicate * predicate)1884 void cStats::AddMovementPredicate(cOrgMovementPredicate* predicate)
1885 {
1886   m_movement_predicates.push_back(predicate);
1887 }
1888 
1889 /*! This method is called whenever an organism moves.*/
Move(cOrganism & org)1890 void cStats::Move(cOrganism& org) {
1891   // Check to see if this message matches any of our predicates.
1892   for(movement_pred_ptr_list::iterator i=m_movement_predicates.begin();
1893       i!=m_movement_predicates.end(); ++i) {
1894     (**i)(org); // Predicate is responsible for tracking info about movement.
1895   }
1896 }
1897 
1898 // deme predicate stats
IncEventCount(int x,int y)1899 void cStats::IncEventCount(int x, int y) {
1900   relative_pos_event_count.ElementAt(x,y)++;
1901 }
1902 
IncPredSat(int cell_id)1903 void cStats::IncPredSat(int cell_id) {
1904   cPopulation& pop = m_world->GetPopulation();
1905   int deme_id = pop.GetCell(cell_id).GetDemeID();
1906   std::pair<int, int> pos = pop.GetDeme(deme_id).GetCellPosition(cell_id);
1907   relative_pos_pred_sat.ElementAt(pos.first, pos.second)++;
1908 }
1909 
AddDemeResourceThresholdPredicate(cString & name)1910 void cStats::AddDemeResourceThresholdPredicate(cString& name) {
1911 	demeResourceThresholdPredicateMap[name] = 0;
1912 }
1913 
IncDemeResourceThresholdPredicate(cString & name)1914 void cStats::IncDemeResourceThresholdPredicate(cString& name) {
1915 	++demeResourceThresholdPredicateMap[name];
1916 }
1917 
PrintDemeResourceThresholdPredicate(const cString & filename)1918 void cStats::PrintDemeResourceThresholdPredicate(const cString& filename)
1919 {
1920   cDataFile& df = m_world->GetDataFile(filename);
1921   df.WriteComment("Avida deme resource threshold predicate data");
1922 	df.WriteComment("Number of deme reproduced by a specific threshold since last update that data was printed");
1923   df.WriteTimeStamp();
1924 
1925 	if(demeResourceThresholdPredicateMap.size() > 0) {
1926 		df.Write(GetUpdate(), "Update [update]");
1927 		for(map<cString, int>::iterator iter = demeResourceThresholdPredicateMap.begin(); iter != demeResourceThresholdPredicateMap.end(); ++iter) {
1928 			df.Write(iter->second, iter->first);
1929 			iter->second = 0;
1930 			assert(iter->second == 0 && demeResourceThresholdPredicateMap[iter->first] == 0);
1931 		}
1932 		df.Endl();
1933 	}
1934 }
1935 
1936 /*! This method prints information contained within all active message predicates.
1937 
1938  Each row of the data file has the following format:
1939    update predicate_name predicate_data...
1940  */
PrintPredicatedMessages(const cString & filename)1941 void cStats::PrintPredicatedMessages(const cString& filename)
1942 {
1943   cDataFile& df = m_world->GetDataFile(filename);
1944   df.WriteColumnDesc("update [update]");
1945   df.WriteColumnDesc("predicate name: [pname]");
1946   df.WriteColumnDesc("predicate data: [pdata]");
1947   df.FlushComments();
1948 
1949   std::ofstream& out = df.GetOFStream();
1950   for(message_pred_ptr_list::iterator i=m_message_predicates.begin();
1951     i!=m_message_predicates.end(); ++i) {
1952       (*i)->Print(GetUpdate(), out);
1953       (*i)->Reset();
1954   }
1955 //  df.Endl();
1956 }
1957 
PrintPredSatFracDump(const cString & filename)1958 void cStats::PrintPredSatFracDump(const cString& filename) {
1959   cDataFile& df = m_world->GetDataFile(filename);
1960   df.WriteComment( "Displays the fraction of events detected in cell since last print.\n" );
1961   df.FlushComments();
1962   cString UpdateStr = cStringUtil::Stringf( "%07i", GetUpdate() ) + " = [ ...";
1963   df.WriteRaw(UpdateStr);
1964 
1965   int rows = relative_pos_pred_sat.GetNumRows();
1966   int cols = relative_pos_pred_sat.GetNumCols();
1967   for (int x = 0; x < rows; x++) {
1968     for (int y = 0; y < cols; y++) {
1969       double data;
1970       if(relative_pos_event_count.ElementAt(x,y) == 0) {
1971         data = 0.0;
1972       } else {
1973         data = (double) relative_pos_pred_sat.ElementAt(x,y) / (double) relative_pos_event_count.ElementAt(x,y);
1974       }
1975       df.WriteBlockElement(data, x*cols+y, cols);
1976     }
1977   }
1978   df.WriteRaw("];");
1979   df.Endl();
1980 
1981   relative_pos_pred_sat.SetAll(0);
1982   relative_pos_event_count.SetAll(0);
1983 }
1984 
DemePreReplication(cDeme & source_deme,cDeme & target_deme)1985 void cStats::DemePreReplication(cDeme& source_deme, cDeme& target_deme)
1986 {
1987   ++m_deme_num_repls;
1988   ++m_total_deme_num_repls;
1989   m_deme_gestation_time.Add(source_deme.GetAge());
1990   m_deme_births.Add(source_deme.GetBirthCount());
1991   m_deme_merit.Add(source_deme.GetHeritableDemeMerit().GetDouble());
1992   m_deme_generation.Add(source_deme.GetGeneration());
1993   m_deme_density.Add(source_deme.GetDensity());
1994 
1995   if(source_deme.isTreatable()) {
1996     ++m_deme_num_repls_treatable;
1997     m_deme_gestation_time_treatable.Add(source_deme.GetAge());
1998     m_deme_births_treatable.Add(source_deme.GetBirthCount());
1999     m_deme_merit_treatable.Add(source_deme.GetHeritableDemeMerit().GetDouble());
2000     m_deme_generation_treatable.Add(source_deme.GetGeneration());
2001     m_deme_density_treatable.Add(source_deme.GetDensity());
2002   } else {
2003     ++m_deme_num_repls_untreatable;
2004     m_deme_gestation_time_untreatable.Add(source_deme.GetAge());
2005     m_deme_births_untreatable.Add(source_deme.GetBirthCount());
2006     m_deme_merit_untreatable.Add(source_deme.GetHeritableDemeMerit().GetDouble());
2007     m_deme_generation_untreatable.Add(source_deme.GetGeneration());
2008     m_deme_density_untreatable.Add(source_deme.GetDensity());
2009   }
2010 
2011 
2012 
2013   /* Track the number of mutations that have occured to the germline as the result of damage resulting from performing metabolic work. Only add to stats if there is a germline... */
2014 
2015   std::pair<double, double> p = source_deme.GetGermlineNumPercent();
2016 
2017   if (p.first >= 0) {
2018     m_ave_germ_size.push_back(p.first);
2019     m_ave_germ_percent.push_back(p.second);
2020 
2021     p = source_deme.GetAveVarGermMut();
2022     m_ave_germ_mut.push_back(p.first);
2023     m_var_germ_mut.push_back(p.second);
2024 
2025     p = source_deme.GetAveVarSomaMut();
2026     m_ave_soma_mut.push_back(p.first);
2027     m_var_soma_mut.push_back(p.second);
2028 
2029     p = source_deme.GetAveVarGermWorkLoad();
2030     m_ave_germ_work.push_back(p.first);
2031     m_var_germ_work.push_back(p.second);
2032 
2033     p = source_deme.GetAveVarSomaWorkLoad();
2034     m_ave_soma_work.push_back(p.first);
2035     m_var_soma_work.push_back(p.second);
2036 
2037   }
2038 }
2039 
2040 
2041 /*! This method is a generic hook for post-deme-replication stat tracking.  We
2042 currently only track the genotype ids of all the founders of each deme in the population.
2043 Note that we capture genotype ids at the time of deme replication, so we unfortunately
2044 lose the ancestral deme founders.
2045 */
DemePostReplication(cDeme & source_deme,cDeme & target_deme)2046 void cStats::DemePostReplication(cDeme& source_deme, cDeme& target_deme)
2047 {
2048   m_deme_founders[target_deme.GetID()] = target_deme.GetGenotypeIDs();
2049 }
2050 
2051 
2052 /*! Called immediately prior to germline replacement.
2053 */
GermlineReplication(cGermline & source_germline,cGermline & target_germline)2054 void cStats::GermlineReplication(cGermline& source_germline, cGermline& target_germline)
2055 {
2056   m_germline_generation.Add(source_germline.Size());
2057 }
2058 
2059 
2060 
2061 
2062 
2063 
2064 /*! Print statistics related to deme replication.  Currently only prints the
2065 number of deme replications since the last time PrintDemeReplicationData was
2066 invoked.
2067 */
PrintDemeReplicationData(const cString & filename)2068 void cStats::PrintDemeReplicationData(const cString& filename)
2069 {
2070   cDataFile& df = m_world->GetDataFile(filename);
2071 
2072   df.WriteComment("Avida deme replication data");
2073   df.WriteTimeStamp();
2074   df.Write(GetUpdate(), "Update [update]");
2075   df.Write(m_deme_num_repls, "Number of deme replications [numrepl]");
2076   df.Write(m_deme_gestation_time.Average(), "Mean deme gestation time [gesttime]");
2077   df.Write(m_deme_births.Average(), "Mean number of births within replicated demes [numbirths]");
2078   df.Write(m_deme_merit.Average(), "Mean heritable merit of replicated demes [merit]");
2079   df.Write(m_deme_generation.Average(), "Mean generation of replicated demes [generation]");
2080   df.Write(m_deme_density.Average(), "Mean density of replicated demes [density]");
2081   df.Endl();
2082 
2083   m_deme_num_repls = 0;
2084   m_deme_gestation_time.Clear();
2085   m_deme_births.Clear();
2086   m_deme_merit.Clear();
2087   m_deme_generation.Clear();
2088 	m_deme_density.Clear();
2089 
2090 }
2091 
2092 /*! Print statistics related to whether or not the demes are sequestering the germline...   Currently prints information from the last 100 deme replications events.
2093  */
PrintDemeGermlineSequestration(const cString & filename)2094 void cStats::PrintDemeGermlineSequestration(const cString& filename)
2095 {
2096   cDataFile& df = m_world->GetDataFile(filename);
2097 
2098   df.WriteComment("Avida deme germline sequestration data");
2099   df.WriteTimeStamp();
2100   df.Write(GetUpdate(), "Update [update]");
2101 
2102   while(m_ave_germ_mut.size()>100) { m_ave_germ_mut.pop_front(); }
2103   while(m_var_germ_mut.size()>100) { m_var_germ_mut.pop_front(); }
2104   while(m_ave_soma_mut.size()>100) { m_ave_soma_mut.pop_front(); }
2105   while(m_var_soma_mut.size()>100) { m_var_soma_mut.pop_front(); }
2106   while(m_ave_germ_size.size()>100) { m_ave_germ_size.pop_front(); }
2107   while(m_ave_germ_percent.size()>100) { m_ave_germ_percent.pop_front(); }
2108   while(m_ave_germ_work.size()>100) { m_ave_germ_work.pop_front(); }
2109   while(m_var_germ_work.size()>100) { m_var_germ_work.pop_front(); }
2110   while(m_ave_soma_work.size()>100) { m_ave_soma_work.pop_front(); }
2111   while(m_var_soma_work.size()>100) { m_var_soma_work.pop_front(); }
2112 
2113   if(m_ave_germ_mut.empty()) {
2114     df.Write(0.0, "Mean absolute germ size [m_ave_germ_size]");
2115 		df.Write(0.0, "Mean percent of germ size [m_ave_germ_percent]");
2116 		df.Write(0.0, "Mean number of mutations to germline [m_ave_germ_mut]");
2117 		df.Write(0.0, "Mean variance of mutations to germline [m_var_germ_mut]");
2118 		df.Write(0.0, "Mean number of mutations to soma [m_ave_soma_mut]");
2119 		df.Write(0.0, "Mean variance of mutations to soma [m_var_soma_mut]");
2120 		df.Write(0.0, "Mean germ workload [m_ave_germ_work]");
2121 		df.Write(0.0, "Mean variance of germ workload [m_var_germ_work]");
2122     df.Write(0.0, "Mean soma workload [m_ave_soma_work]");
2123 		df.Write(0.0, "Mean variance of soma workload [m_var_soma_work]");
2124 	}
2125   else {
2126     df.Write(std::accumulate(m_ave_germ_size.begin(), m_ave_germ_size.end(), 0.0)/m_ave_germ_size.size(), "Mean absolute germ size [m_ave_germ_size]");
2127 		df.Write(std::accumulate(m_ave_germ_percent.begin(), m_ave_germ_percent.end(), 0.0)/m_ave_germ_percent.size(), "Mean percent of germ size [m_ave_germ_percent]");
2128 		df.Write(std::accumulate(m_ave_germ_mut.begin(), m_ave_germ_mut.end(), 0.0)/m_ave_germ_mut.size(), "Mean number of mutations to germline [m_ave_germ_mut]");
2129 		df.Write(std::accumulate(m_var_germ_mut.begin(), m_var_germ_mut.end(), 0.0)/m_var_germ_mut.size(), "Mean variance of mutations to germline [m_var_germ_mut]");
2130 		df.Write(std::accumulate(m_ave_soma_mut.begin(), m_ave_soma_mut.end(), 0.0)/m_ave_soma_mut.size(), "Mean number of mutations to soma [m_ave_soma_mut]");
2131 		df.Write(std::accumulate(m_var_soma_mut.begin(), m_var_soma_mut.end(), 0.0)/m_var_soma_mut.size(), "Mean variance of mutations to soma [m_var_soma_mut]");
2132 		df.Write(std::accumulate(m_ave_germ_work.begin(), m_ave_germ_work.end(), 0.0)/m_ave_germ_work.size(), "Mean germ workload [m_ave_germ_work]");
2133 		df.Write(std::accumulate(m_var_germ_work.begin(), m_var_germ_work.end(), 0.0)/m_var_germ_work.size(), "Mean variance of germ workload [m_var_germ_work]");
2134     df.Write(std::accumulate(m_ave_soma_work.begin(), m_ave_soma_work.end(), 0.0)/m_ave_soma_work.size(), "Mean soma workload [m_ave_soma_work]");
2135 		df.Write(std::accumulate(m_var_soma_work.begin(), m_var_soma_work.end(), 0.0)/m_var_soma_work.size(), "Mean variance of soma workload [m_var_soma_work]");
2136 
2137   }
2138 
2139   df.Endl();
2140 
2141 }
2142 
2143 /*! Print statistics related to whether or not the demes are sequestering the germline...
2144  Currently prints information for each org in each deme.
2145  */
PrintDemeOrgGermlineSequestration(const cString & filename)2146 void cStats::PrintDemeOrgGermlineSequestration(const cString& filename)
2147 {
2148 
2149   cDataFile& df = m_world->GetDataFile(filename);
2150 	df.WriteComment("Cell data per udpate.");
2151 	df.WriteTimeStamp();
2152 
2153   cPopulation& pop = m_world->GetPopulation();
2154 	static const int numDemes = pop.GetNumDemes();
2155 
2156   for(int i = 0; i < numDemes; ++i) {
2157     cDeme& deme = pop.GetDeme(i);
2158     df.Write(GetUpdate(), "Update [update]");
2159     df.Write(deme.GetDemeID(), "Deme ID for cell [demeid]");
2160     df.Write(deme.GetTotalResourceAmountConsumed(), "Deme resources consumed [demeres]");
2161 
2162     tArray<int> react_count = deme.GetReactionCount();
2163     for (int k=0; k<react_count.GetSize(); ++k){
2164       react_count[k] = 0;
2165     }
2166 
2167     int numGerm = 0;
2168     int numMut = 0;
2169     int numPresent = 0;
2170 
2171     for (int j=0; j<deme.GetSize(); ++j) {
2172 
2173       cPopulationCell& cell = deme.GetCell(j);
2174       if (cell.IsOccupied()) {
2175         cOrganism* o = cell.GetOrganism();
2176         int isGerm = 0;
2177         if (o->IsGermline()) isGerm = 1;
2178 
2179         df.Write(isGerm, "Org is germ line [isgerm]");
2180         df.Write(o->GetNumOfPointMutationsApplied(), "Number of point mutations [numPoint]");
2181         if (isGerm) numGerm++;
2182         numMut += o->GetNumOfPointMutationsApplied();
2183         numPresent++;
2184 
2185          tArray<int> org_react_count = o->GetPhenotype().GetCumulativeReactionCount();
2186          for (int k=0; k<org_react_count.GetSize(); ++k){
2187            react_count[k] += org_react_count[k];
2188          }
2189       }
2190         // Cell is not occuppied.
2191       else {
2192         df.Write(2, "Org is germ line [isgerm]");
2193         df.Write(0, "Number of point mutations [numPoint]");
2194       }
2195     }
2196     for (int k=0; k<react_count.GetSize(); ++k){
2197       df.Write(react_count[k], "reaction");
2198     }
2199     df.Write(numGerm, "numGerm");
2200     df.Write(numPresent, "numPresent");
2201     df.Write(numMut, "numMut");
2202 
2203 
2204 
2205     df.Endl();
2206 	}
2207 }
2208 
2209 
2210 /*! Print the genotype ID and genotypes of the founders of recently born demes that use germline method = 3,
2211  where the organisms flag themselves as part of the germline.
2212 
2213  Only deme "births" (i.e., due to deme replication) are tracked; the ancestral deme founders are lost.
2214  The update column is the update at which this method executes, not the time at which the given deme was born.
2215  */
PrintDemeGLSFounders(const cString & filename)2216 void cStats::PrintDemeGLSFounders(const cString& filename){
2217 
2218 
2219     cDataFile& df = m_world->GetDataFile(filename);
2220 
2221     df.WriteComment("Avida gls deme founder data.");
2222     df.WriteTimeStamp();
2223     df.WriteColumnDesc("Update [update]");
2224     df.WriteColumnDesc("Soure Deme ID [sdemeid]");
2225     df.WriteColumnDesc("Target Deme ID [tdemeid]");
2226     df.WriteColumnDesc("Number of founders [size]");
2227     df.WriteColumnDesc("{target genotype ID, target genome... founder 0, ...}");
2228     df.FlushComments();
2229 
2230     std::ofstream& out = df.GetOFStream();
2231 
2232    //  typedef std::map<std::pair<int, int>, std::vector<std::pair<int, std::string> > > t_gls_founder_map;
2233 
2234     for(t_gls_founder_map::iterator i=m_gls_deme_founders.begin(); i!=m_gls_deme_founders.end(); ++i) {
2235       out << GetUpdate() << " " << i->first.first << " " << i->first.second << " " << i->second.size();
2236       for(std::vector<std::pair<int, std::string> >::iterator j=i->second.begin(); j!=i->second.end(); ++j) {
2237         out << " " << (*j).first << " " << (*j).second;
2238 //        out << " " << *j;
2239       }
2240       df.Endl();
2241     }
2242     m_gls_deme_founders.clear();
2243 
2244 }
2245 
2246 //! Track GLS Deme Founder Data
TrackDemeGLSReplication(int source_deme_id,int target_deme_id,std::vector<std::pair<int,std::string>> founders)2247 void cStats::TrackDemeGLSReplication(int source_deme_id, int target_deme_id,   std::vector<std::pair<int, std::string> > founders){
2248   m_gls_deme_founders[make_pair(source_deme_id, target_deme_id)] = founders;
2249 }
2250 
2251 
2252 
2253 
2254 
2255 /*! Print statistics related to deme replication.  Currently only prints the
2256  number of deme replications since the last time PrintDemeReplicationData was
2257  invoked.
2258  */
PrintDemeTreatableReplicationData(const cString & filename)2259 void cStats::PrintDemeTreatableReplicationData(const cString& filename)
2260 {
2261   cDataFile& df = m_world->GetDataFile(filename);
2262 
2263   df.WriteComment("Avida deme replication data for treatable deme");
2264   df.WriteTimeStamp();
2265   df.Write(GetUpdate(), "Update [update]");
2266   df.Write(m_deme_num_repls_treatable, "Number of deme replications [numrepl]");
2267   df.Write(m_deme_gestation_time_treatable.Average(), "Mean deme gestation time [gesttime]");
2268   df.Write(m_deme_births_treatable.Average(), "Mean number of births within replicated demes [numbirths]");
2269   df.Write(m_deme_merit_treatable.Average(), "Mean heritable merit of replicated demes [merit]");
2270   df.Write(m_deme_generation_treatable.Average(), "Mean generation of replicated demes [generation]");
2271 	df.Write(m_deme_density_treatable.Average(), "Mean density of replicated demes [density]");
2272 
2273   df.Endl();
2274 
2275   m_deme_num_repls_treatable = 0;
2276   m_deme_gestation_time_treatable.Clear();
2277   m_deme_births_treatable.Clear();
2278   m_deme_merit_treatable.Clear();
2279   m_deme_generation_treatable.Clear();
2280 	m_deme_density_treatable.Clear();
2281 }
2282 
2283 /*! Print statistics related to deme replication.  Currently only prints the
2284  number of deme replications since the last time PrintDemeReplicationData was
2285  invoked.
2286  */
PrintDemeUntreatableReplicationData(const cString & filename)2287 void cStats::PrintDemeUntreatableReplicationData(const cString& filename)
2288 {
2289   cDataFile& df = m_world->GetDataFile(filename);
2290 
2291   df.WriteComment("Avida deme replication data for untreatable deme");
2292   df.WriteTimeStamp();
2293   df.Write(GetUpdate(), "Update [update]");
2294   df.Write(m_deme_num_repls_untreatable, "Number of deme replications [numrepl]");
2295   df.Write(m_deme_gestation_time_untreatable.Average(), "Mean deme gestation time [gesttime]");
2296   df.Write(m_deme_births_untreatable.Average(), "Mean number of births within replicated demes [numbirths]");
2297   df.Write(m_deme_merit_untreatable.Average(), "Mean heritable merit of replicated demes [merit]");
2298   df.Write(m_deme_generation_untreatable.Average(), "Mean generation of replicated demes [generation]");
2299 	df.Write(m_deme_density_untreatable.Average(), "Mean density of replicated demes [density]");
2300 
2301   df.Endl();
2302 
2303   m_deme_num_repls_untreatable = 0;
2304   m_deme_gestation_time_untreatable.Clear();
2305   m_deme_births_untreatable.Clear();
2306   m_deme_merit_untreatable.Clear();
2307   m_deme_generation_untreatable.Clear();
2308 	m_deme_density_untreatable.Clear();
2309 }
2310 
2311 
PrintDemeTreatableCount(const cString & filename)2312 void cStats::PrintDemeTreatableCount(const cString& filename)
2313 {
2314   cPopulation& pop = m_world->GetPopulation();
2315 	static const int numDemes = pop.GetNumDemes();
2316 	int treatable(0);
2317 	int untreatable(0);
2318 	for(int i = 0; i < numDemes; ++i) {
2319 		if(pop.GetDeme(i).isTreatable())
2320 			++treatable;
2321 		else
2322 			++untreatable;
2323 	}
2324 
2325 	cDataFile& df = m_world->GetDataFile(filename);
2326 
2327   df.WriteComment("Avida deme replication data for untreatable deme");
2328   df.WriteTimeStamp();
2329   df.Write(GetUpdate(), "Update [update]");
2330   df.Write(treatable, "Number demes treatable");
2331   df.Write(untreatable, "Number demes untreatable");
2332   df.Write(static_cast<double>(treatable)/static_cast<double>(untreatable), "Treatable:untreatable ratio");
2333 
2334   df.Endl();
2335 }
2336 
PrintGermlineData(const cString & filename)2337 void cStats::PrintGermlineData(const cString& filename)
2338 {
2339   cDataFile& df = m_world->GetDataFile(filename);
2340 
2341   df.WriteComment("Avida germline data");
2342   df.WriteTimeStamp();
2343   df.Write(GetUpdate(), "Update [update]");
2344   df.Write(m_germline_generation.Average(), "Mean germline generation of replicated germlines [replgen]");
2345   df.Endl();
2346 
2347   m_germline_generation.Clear();
2348 }
2349 
2350 
2351 /*! Print the genotype IDs of the founders of recently born demes.
2352 
2353 Prints only the most recent set of founding genotype ids for each deme.  If a deme was replaced multiple
2354 times since the last time this method ran, only the most recent is printed.  Only deme "births" (i.e., due
2355 to deme replication) are tracked; the ancestral deme founders are lost.  The update column is the update
2356 at which this method executes, not the time at which the given deme was born.
2357 */
PrintDemeFoundersData(const cString & filename)2358 void cStats::PrintDemeFoundersData(const cString& filename)
2359 {
2360   cDataFile& df = m_world->GetDataFile(filename);
2361 
2362   df.WriteComment("Avida deme founder data.");
2363   df.WriteTimeStamp();
2364   df.WriteColumnDesc("Update [update]");
2365   df.WriteColumnDesc("Deme ID [demeid]");
2366   df.WriteColumnDesc("Number of founders [size]");
2367   df.WriteColumnDesc("{Genotype ID of founder 0, ...}");
2368   df.FlushComments();
2369 
2370   std::ofstream& out = df.GetOFStream();
2371   for(t_founder_map::iterator i=m_deme_founders.begin(); i!=m_deme_founders.end(); ++i) {
2372     out << GetUpdate() << " " << i->first << " " << i->second.size();
2373     for(std::vector<int>::iterator j=i->second.begin(); j!=i->second.end(); ++j) {
2374       out << " " << *j;
2375     }
2376     df.Endl();
2377   }
2378   m_deme_founders.clear();
2379 }
2380 
2381 
PrintPerDemeTasksData(const cString & filename)2382 void cStats::PrintPerDemeTasksData(const cString& filename)
2383 {
2384   cDataFile& df = m_world->GetDataFile(filename);
2385   df.WriteComment("Avida deme tasks data");
2386   df.WriteTimeStamp();
2387   df.WriteComment("First column gives the current update, next columns give the number");
2388   df.WriteComment("of organisms that have the particular task as a component of their merit");
2389   df.WriteComment("in a particular deme");
2390 
2391   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2392 
2393   df.Write(m_update, "Update");
2394   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2395     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2396     for(int j = 0; j < num_tasks; j++) {
2397       df.Write( (deme.GetLastTaskExeCount()[j] > 0), cStringUtil::Stringf("%i.", i) + task_names[j] );
2398     }
2399   }
2400   df.Endl();
2401 }
2402 
2403 
PrintPerDemeTasksExeData(const cString & filename)2404 void cStats::PrintPerDemeTasksExeData(const cString& filename)
2405 {
2406   cDataFile& df = m_world->GetDataFile(filename);
2407   df.WriteComment("Avida deme tasks exe data");
2408   df.WriteTimeStamp();
2409   df.WriteComment("First column gives the current update, next columns give the number");
2410   df.WriteComment("of times a task has contributed to the merit of all organisms");
2411   df.WriteComment("in a particular deme");
2412 
2413   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2414 
2415   df.Write(m_update, "Update");
2416   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2417     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2418     for(int j = 0; j < num_tasks; j++) {
2419       df.Write( deme.GetLastTaskExeCount()[j], cStringUtil::Stringf("%i.", i) + task_names[j] );
2420     }
2421   }
2422   df.Endl();
2423 }
2424 
2425 
PrintAvgDemeTasksExeData(const cString & filename)2426 void cStats::PrintAvgDemeTasksExeData(const cString& filename)
2427 {
2428   cDataFile& df = m_world->GetDataFile(filename);
2429   const int num_demes = m_world->GetPopulation().GetNumDemes();
2430   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2431   cIntSum tasksum;
2432 
2433   df.WriteComment("Avida average deme tasks data");
2434   df.WriteTimeStamp();
2435   df.WriteComment("First column is the update, remaining columns are the average number of times");
2436   df.WriteComment("each task has been executed by the demes");
2437   df.WriteComment(cStringUtil::Stringf("Data based on %i demes and %i tasks", num_demes, num_tasks));
2438 
2439   df.Write(m_update, "Update");
2440 
2441   for(int t = 0; t < num_tasks; t++) {
2442     tasksum.Clear();
2443 
2444     for(int d = 0; d < num_demes; d++) {
2445       cDeme& deme = m_world->GetPopulation().GetDeme(d);
2446       tasksum.Add(deme.GetLastTaskExeCount()[t]);
2447     }
2448     df.Write(tasksum.Average(), task_names[t]);
2449   }
2450   df.Endl();
2451 }
2452 
2453 
PrintAvgTreatableDemeTasksExeData(const cString & filename)2454 void cStats::PrintAvgTreatableDemeTasksExeData(const cString& filename)
2455 {
2456   cDataFile& df = m_world->GetDataFile(filename);
2457   const int num_demes = m_world->GetPopulation().GetNumDemes();
2458   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2459   cIntSum tasksum;
2460 
2461   df.WriteComment("Avida average tasks data for treatable demes");
2462   df.WriteTimeStamp();
2463   df.WriteComment("First column is the update, remaining columns are the average number of times");
2464   df.WriteComment("each task has been executed by treatable demes");
2465   df.WriteComment(cStringUtil::Stringf("Data based on %i demes and %i tasks", num_demes, num_tasks));
2466 
2467   df.Write(m_update, "Update");
2468 
2469   for(int t = 0; t < num_tasks; t++) {
2470     tasksum.Clear();
2471 
2472     for(int d = 0; d < num_demes; d++) {
2473       cDeme& deme = m_world->GetPopulation().GetDeme(d);
2474       if(deme.isTreatable()) {
2475         tasksum.Add(deme.GetLastTaskExeCount()[t]);
2476       }
2477     }
2478     df.Write(tasksum.Average(), task_names[t]);
2479   }
2480   df.Endl();
2481 }
2482 
2483 
PrintAvgUntreatableDemeTasksExeData(const cString & filename)2484 void cStats::PrintAvgUntreatableDemeTasksExeData(const cString& filename) {
2485   cDataFile& df = m_world->GetDataFile(filename);
2486   const int num_demes = m_world->GetPopulation().GetNumDemes();
2487   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2488   cIntSum tasksum;
2489 
2490   df.WriteComment("Avida average tasks data for untreatable demes");
2491   df.WriteTimeStamp();
2492   df.WriteComment("First column is the update, remaining columns are the average number of times");
2493   df.WriteComment("each task has been executed by untreatable demes");
2494   df.WriteComment(cStringUtil::Stringf("Data based on %i demes and %i tasks", num_demes, num_tasks));
2495 
2496   df.Write(m_update, "Update");
2497 
2498   for(int t = 0; t < num_tasks; t++) {
2499     tasksum.Clear();
2500 
2501     for(int d = 0; d < num_demes; d++) {
2502       cDeme& deme = m_world->GetPopulation().GetDeme(d);
2503       if(!deme.isTreatable()) {
2504         tasksum.Add(deme.GetLastTaskExeCount()[t]);
2505       }
2506     }
2507     df.Write(tasksum.Average(), task_names[t]);
2508   }
2509   df.Endl();
2510 }
2511 
2512 
PrintPerDemeReactionData(const cString & filename)2513 void cStats::PrintPerDemeReactionData(const cString& filename)
2514 {
2515   cDataFile& df = m_world->GetDataFile(filename);
2516   df.WriteComment("Avida deme reactions data");
2517   df.WriteTimeStamp();
2518   df.WriteComment("First column gives the current update, all further columns give the number");
2519   df.WriteComment("of currently living organisms each reaction has affected.");
2520 
2521   const int num_reactions = m_world->GetEnvironment().GetReactionLib().GetSize();
2522 
2523   df.Write(m_update,   "Update");
2524   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2525     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2526     for(int j = 0; j < num_reactions; j++) {
2527       df.Write( deme.GetLastReactionCount()[j], cStringUtil::Stringf("%i.", i) + m_world->GetEnvironment().GetReactionLib().GetReaction(j)->GetName()  );
2528     }
2529   }
2530   df.Endl();
2531 }
2532 
PrintDemeTasksData(const cString & filename)2533 void cStats::PrintDemeTasksData(const cString& filename)
2534 {
2535   cDataFile& df = m_world->GetDataFile(filename);
2536   df.WriteComment("Avida deme tasks data");
2537   df.WriteTimeStamp();
2538   df.WriteComment("First column gives the current update, next columns give the number");
2539   df.WriteComment("of organisms per deme that had the given task as a component of their merit");
2540   df.WriteComment("during the lifetime of the deme");
2541 
2542   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2543 
2544   tArray<int> deme_tasks;
2545   deme_tasks.ResizeClear(num_tasks);
2546   deme_tasks.SetAll(num_tasks);
2547   int occupied_demes = 0;
2548   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2549     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2550     if (!deme.IsEmpty()) {
2551       occupied_demes++;
2552       for(int j = 0; j < num_tasks; j++) {
2553         deme_tasks[j] += static_cast<int>(deme.GetLastTaskExeCount()[j] > 0);
2554       }
2555     }
2556   }
2557 
2558   df.Write(m_update,   "Update");
2559   for(int j = 0; j < num_tasks; j++) {
2560     df.Write( static_cast<double>(deme_tasks[j]) / static_cast<double>(occupied_demes), task_names[j] );
2561   }
2562   df.Endl();
2563 }
2564 
PrintDemeTasksExeData(const cString & filename)2565 void cStats::PrintDemeTasksExeData(const cString& filename)
2566 {
2567   cDataFile& df = m_world->GetDataFile(filename);
2568   df.WriteComment("Avida deme tasks exe data");
2569   df.WriteTimeStamp();
2570   df.WriteComment("First column gives the current update, next columns give the number");
2571   df.WriteComment("of times per deme that a given task counted as a component of an");
2572   df.WriteComment("organisms's merit during the lifetime of the deme");
2573 
2574   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2575 
2576   tArray<int> deme_tasks;
2577   deme_tasks.ResizeClear(num_tasks);
2578   deme_tasks.SetAll(num_tasks);
2579   int occupied_demes = 0;
2580   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2581     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2582     if (!deme.IsEmpty()) {
2583       occupied_demes++;
2584       for(int j = 0; j < num_tasks; j++) {
2585         deme_tasks[j] += deme.GetLastTaskExeCount()[j];
2586       }
2587     }
2588   }
2589 
2590   df.Write(m_update,   "Update");
2591   for(int j = 0; j < num_tasks; j++) {
2592     df.Write( static_cast<double>(deme_tasks[j]) / static_cast<double>(occupied_demes), task_names[j] );
2593 	}
2594   df.Endl();
2595 }
2596 
PrintDemeReactionData(const cString & filename)2597 void cStats::PrintDemeReactionData(const cString& filename)
2598 {
2599   cDataFile& df = m_world->GetDataFile(filename);
2600   df.WriteComment("Avida deme reactions data");
2601   df.WriteTimeStamp();
2602   df.WriteComment("First column gives the current update, all further columns give the number");
2603   df.WriteComment("of times each reaction has affected a deme.");
2604 
2605   const int num_reactions = m_world->GetEnvironment().GetReactionLib().GetSize();
2606 
2607   tArray<int> deme_reactions;
2608   deme_reactions.ResizeClear(num_reactions);
2609   deme_reactions.SetAll(0);
2610   int occupied_demes = 0;
2611   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2612     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2613     if (!deme.IsEmpty()) {
2614       occupied_demes++;
2615       for(int j = 0; j < num_reactions; j++) {
2616         deme_reactions[j] += deme.GetLastReactionCount()[j];
2617       }
2618     }
2619   }
2620 
2621   df.Write(m_update,   "Update");
2622   for(int j = 0; j < num_reactions; j++) {
2623     df.Write( static_cast<double>(deme_reactions[j]) / static_cast<double>(occupied_demes), m_world->GetEnvironment().GetReactionLib().GetReaction(j)->GetName() );
2624   }
2625   df.Endl();
2626 }
2627 
PrintDemeOrgTasksData(const cString & filename)2628 void cStats::PrintDemeOrgTasksData(const cString& filename)
2629 {
2630   cDataFile& df = m_world->GetDataFile(filename);
2631   df.WriteComment("Avida deme org tasks data");
2632   df.WriteTimeStamp();
2633   df.WriteComment("First column gives the current update, next columns give the number");
2634   df.WriteComment("of organisms that have the particular task as a component of their merit");
2635   df.WriteComment("in a particular deme when the deme last divided.");
2636 
2637   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2638 
2639   df.Write(m_update,   "Update");
2640   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2641     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2642     for(int j = 0; j < num_tasks; j++) {
2643       df.Write( deme.GetLastOrgTaskCount()[j], cStringUtil::Stringf("%i.", i) + task_names[j] );
2644     }
2645   }
2646   df.Endl();
2647 }
2648 
PrintDemeOrgTasksExeData(const cString & filename)2649 void cStats::PrintDemeOrgTasksExeData(const cString& filename)
2650 {
2651   cDataFile& df = m_world->GetDataFile(filename);
2652   df.WriteComment("Avida deme org tasks exe data");
2653   df.WriteTimeStamp();
2654   df.WriteComment("First column gives the current update, next columns give the number");
2655   df.WriteComment("of times a task has contributed to the merit of all organisms");
2656   df.WriteComment("in a particular deme when the deme last divided.");
2657 
2658   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2659 
2660   df.Write(m_update,   "Update");
2661   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2662     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2663     for(int j = 0; j < num_tasks; j++) {
2664       df.Write( deme.GetLastOrgTaskExeCount()[j], cStringUtil::Stringf("%i.", i) + task_names[j] );
2665     }
2666   }
2667 
2668   df.Endl();
2669 }
2670 
PrintDemeCurrentTaskExeData(const cString & filename)2671 void cStats::PrintDemeCurrentTaskExeData(const cString& filename)
2672 {
2673   cDataFile& df = m_world->GetDataFile(filename);
2674   df.WriteComment("Avida deme current task exe data");
2675   df.WriteTimeStamp();
2676   df.WriteComment("First column gives update number, next columns give the number");
2677   df.WriteComment("of times a given task has been executed in a given deme by");
2678   df.WriteComment("some organism in that deme.");
2679 
2680   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2681   df.Write(m_update, "Update");
2682   for (int deme_num=0; deme_num < m_world->GetPopulation().GetNumDemes(); ++deme_num) {
2683     cDeme& deme = m_world->GetPopulation().GetDeme(deme_num);
2684     for (int task_num=0; task_num < num_tasks; task_num++) {
2685       df.Write(	deme.GetCurTaskExeCount()[task_num],
2686         cStringUtil::Stringf("%i.", deme_num)+task_names[task_num]);
2687     }
2688   }
2689 
2690   df.Endl();
2691 }
2692 
PrintCurrentTaskCounts(const cString & filename)2693 void cStats::PrintCurrentTaskCounts(const cString& filename)
2694 {
2695   ofstream& fp = m_world->GetDataFileOFStream(filename);
2696   fp << "Update " << m_world->GetStats().GetUpdate() << ":" << endl;
2697   for (int y = 0; y < m_world->GetPopulation().GetWorldY(); y++) {
2698     for (int x = 0; x < m_world->GetPopulation().GetWorldX(); x++) {
2699       cPopulationCell& cell = m_world->GetPopulation().GetCell(y * m_world->GetPopulation().GetWorldX() + x);
2700       if (cell.IsOccupied()) {
2701         fp << cell.GetOrganism()->GetPhenotype().GetCurTaskCount()[0] << "\t";
2702       } else {
2703         fp << "---\t";
2704       }
2705     }
2706     fp << endl;
2707   }
2708   fp << endl;
2709 }
2710 
PrintDemeOrgReactionData(const cString & filename)2711 void cStats::PrintDemeOrgReactionData(const cString& filename)
2712 {
2713   cDataFile& df = m_world->GetDataFile(filename);
2714   df.WriteComment("Avida deme org reactions data");
2715   df.WriteTimeStamp();
2716   df.WriteComment("First column gives the current update, all further columns give the number");
2717   df.WriteComment("of currently living organisms each reaction has affected");
2718   df.WriteComment("in a particular deme when the deme last divided.");
2719 
2720   const int num_reactions = m_world->GetEnvironment().GetReactionLib().GetSize();
2721 
2722   df.Write(m_update, "Update");
2723   for (int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2724     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2725     for (int j = 0; j < num_reactions; j++) {
2726       df.Write(deme.GetLastOrgReactionCount()[j], cStringUtil::Stringf("%i.", i) + m_world->GetEnvironment().GetReactionLib().GetReaction(j)->GetName());
2727     }
2728   }
2729   df.Endl();
2730 }
2731 
2732 //@JJB**
PrintDemesTasksData(const cString & filename)2733 void cStats::PrintDemesTasksData(const cString& filename)
2734 {
2735   cDataFile& df = m_world->GetDataFile(filename);
2736   df.WriteComment("Avida current tasks done by each deme");
2737   df.WriteTimeStamp();
2738 
2739   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
2740   df.Write(m_update, "Update");
2741   const int num_demes = m_world->GetPopulation().GetNumDemes();
2742   for (int deme_id = 0; deme_id < num_demes; deme_id++) {
2743     cDeme& deme = m_world->GetPopulation().GetDeme(deme_id);
2744     for (int task_id = 0; task_id < num_tasks; task_id++) {
2745       df.Write(deme.GetTaskCount()[task_id], cStringUtil::Stringf("%i.", deme_id) + task_names[task_id]);
2746     }
2747   }
2748   df.Endl();
2749 }
2750 
2751 //@JJB**
PrintDemesReactionsData(const cString & filename)2752 void cStats::PrintDemesReactionsData(const cString& filename)
2753 {
2754   cDataFile& df = m_world->GetDataFile(filename);
2755   df.WriteComment("Avida current reactions done by each deme");
2756   df.WriteTimeStamp();
2757 
2758   const int num_reactions = m_world->GetEnvironment().GetReactionLib().GetSize();
2759   df.Write(m_update, "Update");
2760   const int num_demes = m_world->GetPopulation().GetNumDemes();
2761   for (int deme_id = 0; deme_id < num_demes; deme_id++) {
2762     cDeme& deme = m_world->GetPopulation().GetDeme(deme_id);
2763     for (int reaction_id = 0; reaction_id < num_reactions; reaction_id++) {
2764       df.Write(deme.GetReactionCount()[reaction_id], cStringUtil::Stringf("%i.", deme_id) + m_world->GetEnvironment().GetReactionLib().GetReaction(reaction_id)->GetName());
2765     }
2766   }
2767   df.Endl();
2768 }
2769 
2770 //@JJB**
PrintDemesFitnessData(const cString & filename)2771 void cStats::PrintDemesFitnessData(const cString& filename)
2772 {
2773   cDataFile& df = m_world->GetDataFile(filename);
2774   df.WriteComment("Avida competition fitness for each deme");
2775   df.WriteTimeStamp();
2776 
2777   df.Write(m_update, "Update");
2778   const int num_demes = m_world->GetPopulation().GetNumDemes();
2779   for (int deme_id = 0; deme_id < num_demes; deme_id++) {
2780     //df.Write(m_deme_fitness[deme_id], cStringUtil::Stringf("%i.Fitness", deme_id));
2781   }
2782   df.Endl();
2783 }
2784 
PrintPerDemeGenPerFounderData(const cString & filename)2785 void cStats::PrintPerDemeGenPerFounderData(const cString& filename)
2786 {
2787   cDataFile& df = m_world->GetDataFile(filename);
2788   df.WriteComment("Avida org generations between deme founders");
2789   df.WriteTimeStamp();
2790   df.WriteComment("First column gives the current update, all further columns give the number");
2791   df.WriteComment("number of generations that passed between the parent and current deme's founders");
2792 
2793   df.Write(m_update, "Update");
2794   for (int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2795     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2796     double val = deme.GetGenerationsPerLifetime();
2797     if (deme.IsEmpty()) val = -1;
2798     df.Write(val, cStringUtil::Stringf("deme.%i", i));
2799   }
2800   df.Endl();
2801 }
2802 
PrintDemeMigrationSuicidePoints(const cString & filename)2803 void cStats::PrintDemeMigrationSuicidePoints(const cString& filename)
2804 {
2805   cDataFile& df = m_world->GetDataFile(filename);
2806   df.WriteComment("Avida average stats");
2807   df.WriteTimeStamp();
2808 
2809 
2810   df.Write(m_update, "Update");
2811   double max_points = 0;
2812   double min_points = -1;
2813   double total_points = 0;
2814   double temp_points = 0;
2815   int max_suicides = 0;
2816   int min_suicides = -1;
2817   double total_suicides = 0;
2818   int temp_suicides = 0;
2819   int max_migrations = 0;
2820   int min_migrations = -1;
2821   double total_migrations = 0;
2822   int temp_migrations = 0;
2823   int deme_count = 0;
2824 
2825 
2826   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2827     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2828 
2829     temp_points = deme.GetNumberOfPoints();
2830     temp_suicides = deme.GetSuicides();
2831     temp_migrations = deme.GetMigrationsOut();
2832 
2833 
2834     // Calculate Min
2835     if ((min_points == -1) || (temp_points < min_points)) {
2836       min_points = temp_points;
2837     }
2838     if ((min_suicides == -1) || (temp_suicides < min_suicides)) {
2839       min_suicides = temp_suicides;
2840     }
2841     if ((min_migrations == -1) || (temp_migrations < min_migrations)) {
2842       min_migrations = temp_migrations;
2843     }
2844 
2845     // Calculate Max
2846     if (temp_points > max_points) max_points = temp_points;
2847     if (temp_suicides > max_suicides) max_suicides = temp_suicides;
2848     if (temp_migrations > max_migrations) max_migrations = temp_migrations;
2849 
2850     total_points += temp_points;
2851     total_suicides += temp_suicides;
2852     total_migrations += temp_migrations;
2853 
2854     if (temp_points > 0) deme_count++;
2855   }
2856 
2857   df.Write((total_points/m_world->GetPopulation().GetNumDemes()), "AveragePoints[avpoints]" );
2858   df.Write(min_points, "MinPoints[minpoints]" );
2859   df.Write(max_points, "MaxPoints[maxpoints]" );
2860   df.Write(deme_count, "DemesWithPoints[demeswithpoints]");
2861   df.Write((total_suicides/m_world->GetPopulation().GetNumDemes()), "AverageSuicides[avsuicides]" );
2862   df.Write(min_suicides, "MinSuicides[minsuicides]" );
2863   df.Write(max_suicides, "MaxSuicides[maxsuicides]" );
2864   df.Write((total_migrations/m_world->GetPopulation().GetNumDemes()), "AverageMigrations[avmigrations]" );
2865   df.Write(min_migrations, "MinMigrations[minmigrations]" );
2866   df.Write(max_migrations, "MaxMigrations[maxmigrations]" );
2867   df.Write((total_suicides/total_migrations), "SuicideMigrationRate[suicidemigrationrate]" );
2868 
2869   df.Endl();
2870 }
2871 
2872 
CompeteDemes(const std::vector<double> & fitness)2873 void cStats::CompeteDemes(const std::vector<double>& fitness)
2874 {
2875   m_deme_fitness = fitness;
2876 }
2877 
2878 
PrintDemeCompetitionData(const cString & filename)2879 void cStats::PrintDemeCompetitionData(const cString& filename)
2880 {
2881   cDataFile& df = m_world->GetDataFile(filename);
2882 
2883   df.WriteComment("Avida compete demes data");
2884   df.WriteTimeStamp();
2885   df.Write(m_update, "Update [update]");
2886 
2887   double avg = std::accumulate(m_deme_fitness.begin(), m_deme_fitness.end(), 0.0);
2888   if(avg > 0.0) {
2889     avg /= m_deme_fitness.size();
2890   }
2891   df.Write(avg, "Avg. deme fitness [avgfit]");
2892   if(m_deme_fitness.size() > 0) {
2893     df.Write(*std::max_element(m_deme_fitness.begin(), m_deme_fitness.end()), "Max. deme fitness [maxfit]");
2894   } else {
2895     df.Write(0.0, "Max. deme fitness [maxfit]");
2896   }
2897   df.Endl();
2898 
2899   m_deme_fitness.clear();
2900 }
2901 
2902 
2903 /*! Prints the cell data from every cell, including the deme for that cell. */
PrintCellData(const cString & filename)2904 void cStats::PrintCellData(const cString& filename)
2905 {
2906   cDataFile& df = m_world->GetDataFile(filename);
2907   df.WriteComment("Cell data per udpate.");
2908   df.WriteTimeStamp();
2909 
2910   for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
2911     const cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
2912     df.Write(GetUpdate(), "Update [update]");
2913     df.Write(cell.GetID(), "Global cell ID [globalid]");
2914     df.Write(cell.GetDemeID(), "Deme ID for cell [demeid]");
2915     df.Write(cell.GetCellData(), "Cell data [data]");
2916     df.Endl();
2917   }
2918 }
2919 
2920 
PrintCurrentOpinions(const cString & filename)2921 void cStats::PrintCurrentOpinions(const cString& filename)
2922 {
2923   cDataFile& df = m_world->GetDataFile(filename);
2924   df.WriteComment("Current opinions of each organism.");
2925   df.WriteTimeStamp();
2926   df.WriteComment("1: Update [update]");
2927   df.WriteComment("2: Global cell ID [globalid]");
2928   df.WriteComment("3: Current opinion [opinion]");
2929   df.WriteComment("4: Cell ID of opinion [cellid]");
2930   df.FlushComments();
2931 
2932   // Build the cell id map:
2933   std::map<int,int> data_id_map;
2934   for (int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
2935     const cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
2936     data_id_map[cell.GetCellData()] = cell.GetID();
2937   }
2938 
2939   for (int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
2940     const cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
2941     df.WriteAnonymous(GetUpdate());
2942     df.WriteAnonymous(cell.GetID());
2943     if (cell.IsOccupied() && cell.GetOrganism()->HasOpinion()) {
2944       int opinion = cell.GetOrganism()->GetOpinion().first;
2945       df.WriteAnonymous(opinion);
2946       if (data_id_map.find(opinion) != data_id_map.end()) {
2947         df.WriteAnonymous(data_id_map[opinion]);
2948       } else {
2949         df.WriteAnonymous(-1);
2950       }
2951     } else {
2952       df.WriteAnonymous(0);
2953       df.WriteAnonymous(-1);
2954     }
2955     df.Endl();
2956   }
2957 }
2958 
2959 
PrintOpinionsSetPerDeme(const cString & filename)2960 void cStats::PrintOpinionsSetPerDeme(const cString& filename) {
2961 	cDataFile& df = m_world->GetDataFile(filename);
2962 	df.WriteComment("Current fractions of opinions set in deme.");
2963 	df.WriteComment("This files shows data for both treatable and untreatable demes.");
2964 	df.WriteTimeStamp();
2965 
2966 	cIntSum    treatableOpinionCounts, untreatableOpinionCounts;
2967 	cDoubleSum treatableDensityCounts, untreatableDensityCounts;
2968 	treatableOpinionCounts.Clear();
2969 	untreatableOpinionCounts.Clear();
2970 	treatableDensityCounts.Clear();
2971 	untreatableDensityCounts.Clear();
2972 
2973 	for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
2974     cDeme& deme = m_world->GetPopulation().GetDeme(i);
2975 		int demeSize = deme.GetSize();
2976 		if(deme.isTreatable()) {
2977 			// accumultate counts for treatable demes
2978 			for(int orgID = 0; orgID < demeSize; ++orgID) {
2979 				treatableOpinionCounts.Add(deme.GetNumOrgsWithOpinion());
2980 				treatableDensityCounts.Add(deme.GetDensity());
2981 			}
2982 		} else {
2983 			// accumultate counts for untreatable demes
2984 			for(int orgID = 0; orgID < demeSize; ++orgID) {
2985 				untreatableOpinionCounts.Add(deme.GetNumOrgsWithOpinion());
2986 				untreatableDensityCounts.Add(deme.GetDensity());
2987 			}
2988 		}
2989 	}
2990 
2991 	df.Write(GetUpdate(), "Update [update]");
2992 
2993 	if(treatableOpinionCounts.N() > 0 && untreatableOpinionCounts.N() > 0) {
2994 		df.Write(treatableOpinionCounts.Average(), "Average number of opinions set in Treatable demes");
2995 		df.Write(untreatableOpinionCounts.Average(), "Average number of opinions set in Unreatable demes");
2996 		df.Write(treatableDensityCounts.Average(), "Average density of Treatable demes");
2997 		df.Write(untreatableDensityCounts.Average(), "Average density of Unreatable demes");
2998 	} else {
2999 		df.Write(untreatableOpinionCounts.Average(), "Average number of opinions set in demes");
3000 		df.Write(untreatableDensityCounts.Average(), "Average density of demes");
3001 	}
3002 	df.Endl();
3003 }
3004 
3005 /*! Called when an organism issues a flash instruction.
3006 
3007  We do some pretty detailed tracking here in order to support the use of flash
3008  messages in deme competition.  All flashes are tracked per deme.
3009 
3010  Because we're tracking highly detailed information about flashes, if
3011  someone forgets to include the print event for synchronization, it's highly
3012  likely that Avida will run out of memory (not that this has happened *ahem*).
3013  So, the first time this method is called, we check to make sure that at least one
3014  of the print events is also called, otherwise we throw an error.
3015  */
SentFlash(cOrganism & organism)3016 void cStats::SentFlash(cOrganism& organism) {
3017 	static bool event_checked=false;
3018 	if(!event_checked && (m_world->GetEventsList() != 0)) {
3019 		if(!m_world->GetEventsList()->IsEventUpcoming("PrintSynchronizationData")
3020 			 && !m_world->GetEventsList()->IsEventUpcoming("PrintDetailedSynchronizationData")) {
3021 			m_world->GetDriver().RaiseFatalException(-1, "When using the flash instruction, either the PrintSynchronizationData or PrintDetailedSynchronizationData events must also be used.");
3022 		}
3023 		event_checked = true;
3024 	}
3025 
3026   ++m_flash_count;
3027 	if(organism.GetOrgInterface().GetDeme() != 0) {
3028 		const cDeme* deme = organism.GetOrgInterface().GetDeme();
3029 		m_flash_times[GetUpdate()][deme->GetID()].push_back(deme->GetRelativeCellID(organism.GetCellID()));
3030 	}
3031 }
3032 
3033 
3034 /*! Print statistics about synchronization flashes. */
PrintSynchronizationData(const cString & filename)3035 void cStats::PrintSynchronizationData(const cString& filename) {
3036   cDataFile& df = m_world->GetDataFile(filename);
3037 
3038   df.WriteComment("Avida synchronization data");
3039   df.WriteTimeStamp();
3040   df.Write(m_update, "Update [update]");
3041   df.Write(m_flash_count, "Flash count [fcount]");
3042   df.Endl();
3043 
3044   m_flash_count = 0;
3045 	m_flash_times.clear();
3046 }
3047 
3048 
3049 /*! Print detailed synchronization data. */
PrintDetailedSynchronizationData(const cString & filename)3050 void cStats::PrintDetailedSynchronizationData(const cString& filename) {
3051   cDataFile& df = m_world->GetDataFile(filename);
3052 
3053   df.WriteComment("Detailed Avida synchronization data");
3054   df.WriteComment("Rows are (update, demeid, cellid) tuples, representing the update at which that cell flashed.");
3055   df.WriteTimeStamp();
3056 
3057 	for(PopulationFlashes::iterator i=m_flash_times.begin(); i!=m_flash_times.end(); ++i) {
3058 		for(DemeFlashes::iterator j=i->second.begin(); j!=i->second.end(); ++j) {
3059 			for(CellFlashes::iterator k=j->second.begin(); k!=j->second.end(); ++k) {
3060 				df.Write(i->first, "Update [update]");
3061 				df.Write(j->first, "Deme ID [demeid]");
3062 				df.Write(*k, "Deme-relative cell ID that issued a flash at this update [relcellid]");
3063 				df.Endl();
3064 			}
3065 		}
3066 	}
3067 
3068 	m_flash_times.clear();
3069 }
3070 
3071 
3072 /*! Called when a deme reaches consensus. */
ConsensusReached(const cDeme & deme,cOrganism::Opinion consensus,int cellid)3073 void cStats::ConsensusReached(const cDeme& deme, cOrganism::Opinion consensus, int cellid) {
3074 	m_consensi.push_back(ConsensusRecord(GetUpdate(), deme.GetID(), consensus, cellid));
3075 }
3076 
3077 
3078 /*! Print "simple" consensus information. */
PrintSimpleConsensusData(const cString & filename)3079 void cStats::PrintSimpleConsensusData(const cString& filename) {
3080 	cDataFile& df = m_world->GetDataFile(filename);
3081 
3082   df.WriteComment("Avida consensus data");
3083   df.WriteTimeStamp();
3084   df.Write(GetUpdate(), "Update [update]");
3085   df.Write((double)m_consensi.size(), "Consensus count [count]");
3086   df.Endl();
3087 	m_consensi.clear();
3088 }
3089 
3090 
3091 /*! Print information about demes that have reached consensus. */
PrintConsensusData(const cString & filename)3092 void cStats::PrintConsensusData(const cString& filename) {
3093   cDataFile& df = m_world->GetDataFile(filename);
3094 
3095   df.WriteComment("Avida consensus data");
3096   df.WriteTimeStamp();
3097 	df.WriteColumnDesc("Update [update]");
3098 	df.WriteColumnDesc("Deme ID [demeid]");
3099 	df.WriteColumnDesc("Consensus value [consensus]");
3100 	df.WriteColumnDesc("Cell ID [cellid]");
3101 	df.FlushComments();
3102 
3103 	for(Consensi::iterator i=m_consensi.begin(); i!=m_consensi.end(); ++i) {
3104 		df.Write(i->update, "Update [update]");
3105 		df.Write(i->deme_id, "Deme ID [demeid]");
3106 		df.Write(i->consensus, "Consensus value [consensus]");
3107 		df.Write(i->cell_id, "Cell ID [cellid]");
3108 		df.Endl();
3109 	}
3110 	m_consensi.clear();
3111 }
3112 
3113 
PrintNumOrgsKilledData(const cString & filename)3114 void cStats::PrintNumOrgsKilledData(const cString& filename)
3115 {
3116   cDataFile& df = m_world->GetDataFile(filename);
3117 
3118   df.WriteComment("Organisms killed using kill actions");
3119   df.WriteTimeStamp();
3120   df.WriteComment("First column is the current update and the second column lists the number of organisms killed");
3121 
3122   df.Write(m_update,   "Update");
3123   df.Write(sum_orgs_killed.Average(), "Avg Num Orgs Killed");
3124   df.Write(sum_unoccupied_cell_kill_attempts.Average(), "Avg Num Unoccupied Cell Kill Attempts");
3125   df.Write(sum_cells_scanned_at_kill.Average(), "Avg Num Cells Scanned By Kill Event");
3126   df.Endl();
3127 
3128   sum_orgs_killed.Clear();
3129   sum_unoccupied_cell_kill_attempts.Clear();
3130   sum_cells_scanned_at_kill.Clear();
3131 } //End PrintNumOrgsKilledData()
3132 
PrintMigrationData(const cString & filename)3133 void cStats::PrintMigrationData(const cString& filename)
3134 {
3135   cDataFile& df = m_world->GetDataFile(filename);
3136 
3137   df.WriteComment("Number of migrations made using the migratedemes event");
3138   df.WriteTimeStamp();
3139   df.WriteComment("First column is the current update and the second column lists the number of migrations made");
3140 
3141   df.Write(m_update,   "Update");
3142   df.Write(num_migrations, "Num Migrations");
3143   df.Endl();
3144 } //End PrintMigrationData()
3145 
3146 
3147 /* Print information pertinent to direct reciprocity experiments*/
PrintDirectReciprocityData(const cString & filename)3148 void cStats::PrintDirectReciprocityData(const cString& filename){
3149 	cDataFile& df = m_world->GetDataFile(filename);
3150 
3151 	cDoubleSum donations;
3152 	cDoubleSum reciprocations;
3153 	cDoubleSum donors;
3154 	cDoubleSum num_donations_received;
3155 
3156 	cOrganism* org;
3157 
3158 	int num_alt =0;
3159 	int num_coop = 0;
3160 	int num_lin_2 = 0;
3161 	int num_lin_1 = 0;
3162 	int total_org = 0;
3163 
3164 
3165 	df.WriteComment("Avida organism direct reciprocity information");
3166 	df.WriteTimeStamp();
3167 	df.Write(m_update,   "Update [update]");
3168 
3169 
3170   for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
3171     cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
3172 		org = cell.GetOrganism();
3173 
3174     if(cell.IsOccupied()) {
3175 			donations.Add(org->GetNumberOfDonations());
3176 			num_donations_received.Add(org->GetNumberOfDonationsReceived());
3177 			reciprocations.Add(org->GetNumberOfReciprocations());
3178 			donors.Add(org->GetNumberOfDonors());
3179 			if (org->GetNumberOfDonations() > 0) num_alt++;
3180 			if ((org->GetNumberOfDonationsReceived() && org->GetNumberOfDonations()) > 0) num_coop++;
3181 			if (org->GetLineageLabel() == 1) num_lin_1++;
3182 			if (org->GetLineageLabel() == 2) num_lin_2++;
3183 			total_org++;
3184 	  }
3185 	}
3186 
3187 	df.Write(donations.Average(), "Avg. donations [donation]");
3188 	df.Write(num_donations_received.Average(), "Avg. donations received [received]");
3189 	df.Write(donors.Average(), "Avg. number of donor partners [partners]");
3190 	df.Write(num_alt, "Number of altruists [altruists]");
3191 	df.Write(num_coop, "Number of cooperators [cooperators]");
3192 	df.Write(num_lin_1, "Number of organisms of lineage 1 [lineage1]");
3193 	df.Write(num_lin_2, "Number of organisms of lineage 2 [lineage2]");
3194 	df.Write(total_org, "Number of organisms in population [popsize]");
3195 
3196   df.Endl();
3197 
3198 
3199 }
3200 
3201 
3202 /* Print information about the string matching... */
PrintStringMatchData(const cString & filename)3203 void cStats::PrintStringMatchData(const cString& filename){
3204 	cDataFile& df = m_world->GetDataFile(filename);
3205 	df.WriteComment("Avida organism string donation information");
3206 	df.WriteTimeStamp();
3207 	df.Write(m_update,   "Update [update]");
3208 	cOrganism* org;
3209 
3210 
3211 	/*
3212 	 // Interate through map of information.
3213 	 map<cString,cDoubleSum>::iterator iter2;
3214 	 for(iter2 = m_string_bits_matched.begin(); iter2 != m_string_bits_matched.end(); iter2++ ) {
3215 	 df.Write(iter2->second.Average(), iter2->first);
3216 	 }
3217 
3218 
3219 	 // Create a map of the current tags in the population .
3220 	 for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
3221 	 cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
3222 	 org = cell.GetOrganism();
3223 
3224 	 if(cell.IsOccupied()) {
3225 	 // Get tag and increment number of orgs.
3226 	 m_tags[org->GetTagLabel()]++;
3227 	 }
3228 	 }
3229 
3230 	 // print the tags
3231 	 map<int, int>::iterator iter;
3232 	 stringstream ss;
3233 	 for(iter = m_tags.begin(); iter != m_tags.end(); iter++ ) {
3234 	 ss << iter->first;
3235 	 string name = ss.str();
3236 	 df.Write(iter->second, name.c_str());
3237 	 iter->second = 0;
3238 	 }*/
3239 
3240 
3241 	// Print data about strings:
3242 	std::map <int, cDoubleSum> m_strings_stored;
3243 	std::map <int, cDoubleSum> m_strings_produced;
3244 	cDoubleSum total;
3245 	int min = -1;
3246 	int onhand = 0;
3247 	int instant_perfect_match = 0;
3248 	int instant_perfect_match_org = 0;
3249 	int nothing  =0;
3250 	int specialists = 0;
3251 	int generalists = 0;
3252 	int type_prod = 0;
3253 
3254 	// Get the number of strings
3255 	int num = m_world->GetEnvironment().GetNumberOfMatchStrings();
3256 	for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
3257     cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
3258 		org = cell.GetOrganism();
3259 		min = -1;
3260 		onhand = 0;
3261 		type_prod = 0;
3262 
3263     if(cell.IsOccupied()) {
3264 			for (int j = 0; j<num; j++) {
3265 				onhand = org->GetNumberStringsOnHand(j);
3266 				if ((min == -1) || (onhand < min)){
3267 					min = onhand;
3268 				}
3269 				m_strings_stored[j].Add(onhand);
3270 				total.Add(onhand);
3271 				m_strings_produced[j].Add(org->GetNumberStringsProduced(j));
3272 
3273 				if (org->GetNumberStringsProduced(j)) type_prod++;
3274 
3275 			}
3276 
3277 			instant_perfect_match += min;
3278 			if (min > 0) instant_perfect_match_org++;
3279 			if (type_prod ==0) nothing++;
3280 			if (type_prod == 1) specialists++;
3281 			if (type_prod > 1) generalists++;
3282 		}
3283 
3284 	}
3285 
3286 	// print the string info
3287 	for (int k=0; k<num; k++) {
3288 		string name = m_world->GetEnvironment().GetMatchString(k).GetData();
3289 		name = "produced" + name;
3290 		df.Write(m_strings_produced[k].Average(), name.c_str());
3291 
3292 		name = m_world->GetEnvironment().GetMatchString(k).GetData();
3293 		name = "stored" + name;
3294 		df.Write(m_strings_stored[k].Average(), name.c_str());
3295 
3296 	}
3297 	df.Write(total.Average(), "totalStoredAverage");
3298 
3299 	// Print number of perfect matches
3300 	df.Write(m_perfect_match.Sum(), "PerfectMatchStringElapse[ps]");
3301 	m_perfect_match.Clear();
3302 	// Print number of perfect matches
3303 	df.Write(m_perfect_match_org.Sum(), "PerfectMatchOrgElapse[pso]");
3304 	m_perfect_match_org.Clear();
3305 	df.Write(instant_perfect_match, "PerfectMatchStringInstant[psi]");
3306 	// Print number of perfect matches
3307 	df.Write(instant_perfect_match_org, "PerfectMatchOrgInstant[psoi]");
3308 	df.Write(nothing, "Producednothing[nothing]");
3309 	df.Write(generalists, "Generalists[generalists]");
3310 	df.Write(specialists, "Specialists[specialists]");
3311 
3312 
3313   df.Endl();
3314 }
3315 
3316 /* Print information about the reputation... */
PrintReputationData(const cString & filename)3317 void cStats::PrintReputationData(const cString& filename){
3318 	cDataFile& df = m_world->GetDataFile(filename);
3319 
3320 	cDoubleSum reputations;
3321 	cDoubleSum donations;
3322 	cDoubleSum reciprocations;
3323 	cDoubleSum donors;
3324 	cDoubleSum k;
3325 	cDoubleSum num_donations_received;
3326 	cDoubleSum amount_donations_received;
3327 	cDoubleSum num_failed_reputation_inc;
3328 	cDoubleSum own_raw_mat;
3329 	cDoubleSum other_raw_mat;
3330 
3331 
3332 	// difference between how many an organism donated & how many it received
3333 	cDoubleSum disparity;
3334 
3335 	cOrganism* org;
3336 	int min_rep = 100;
3337 	int max_rep = 0;
3338 	int cur_rep;
3339 	int num_alt =0;
3340 	int num_coop = 0;
3341 
3342 
3343 
3344 	df.WriteComment("Avida organism reputation information -- average donations, min donations, max donations");
3345 	df.WriteTimeStamp();
3346 	df.Write(m_update,   "Update [update]");
3347 
3348 
3349   for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
3350     cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
3351 		org = cell.GetOrganism();
3352 
3353     if(cell.IsOccupied()) {
3354 			cur_rep = org->GetReputation();
3355 
3356 			if (cur_rep < min_rep) min_rep = cur_rep;
3357 			if (max_rep < cur_rep) max_rep = cur_rep;
3358 			reputations.Add(cur_rep);
3359 			donations.Add(org->GetNumberOfDonations());
3360 			num_donations_received.Add(org->GetNumberOfDonationsReceived());
3361 			amount_donations_received.Add(org->GetAmountOfDonationsReceived());
3362 			own_raw_mat.Add(org->GetSelfRawMaterials());
3363 			other_raw_mat.Add(org->GetOtherRawMaterials());
3364 
3365 			reciprocations.Add(org->GetNumberOfReciprocations());
3366 			donors.Add(org->GetNumberOfDonors());
3367 			num_failed_reputation_inc.Add(org->GetFailedReputationIncreases());
3368 //			k.Add(org->GetK());
3369 
3370 			disparity.Add(org->GetNumberOfDonations() - org->GetOtherRawMaterials());
3371 
3372 			if (org->GetNumberOfDonations() > 0) num_alt++;
3373 			if ((org->GetNumberOfDonationsReceived() && org->GetNumberOfDonations()) > 0) num_coop++;
3374 
3375 
3376 	  }
3377 	}
3378 	df.Write(reputations.Average(), "Avg. reputation [reputation]");
3379 	//	df.Write(reputations.StdDeviation(), "Standard Deviation [repstddev]");
3380 	//	df.Write(min_rep, "Minimum reputation");
3381 	//	df.Write(max_rep, "Maximum reputation");
3382 	df.Write(donations.Average(), "Avg. donations [donation]");
3383 	//	df.Write(num_donations_received.Average(), "Avg. donations received [received]");
3384 	//	df.Write(amount_donations_received.Average(), "Avg. number donations received [amount]");
3385 	//	df.Write(reciprocations.Average(), "Avg. reciprocations [reciprocation]");
3386 	//	df.Write(disparity.Average(), "Disparity between donations and collections [disparity]");
3387 	df.Write(donors.Average(), "Avg. number of donor partners [partners]");
3388 	//	df.Write(num_failed_reputation_inc.Average(), "Avg. number of reputation increase failures [failure]");
3389 	//	df.Write(recip_prob_change.Average(), "Avg. change in reciprocation probability [recipprob]");
3390 
3391 	df.Write(num_alt, "Number of altruists [altruists]");
3392 	df.Write(num_coop, "Number of cooperators [cooperators]");
3393 	df.Write(own_raw_mat.Average(), "Avg. own raw mat [ownrawmat]");
3394 	df.Write(other_raw_mat.Average(), "Avg. other raw mat [otherrawmat]");
3395 	//	df.Write(num_all_strings, "Number of orgs with all strings [allstrings]");
3396 
3397 	//	df.Write(k.Average(), "Avg. k of organisms [k]");
3398 	//	df.Write(m_donate_to_donor, "Number of donate to donor [donatedonor]");
3399 	//	df.Write(m_donate_to_facing, "Number of donate to facing [donatefacing]");
3400 
3401 
3402 
3403   df.Endl();
3404 }
3405 
3406 /*
3407   Cycle through the population -- count the number of altruists in each bin.
3408   Also average their shaded donations.
3409   Check how many prefer the shaded strategy
3410 
3411  */
PrintShadedAltruists(const cString & filename)3412 void cStats::PrintShadedAltruists(const cString& filename) {
3413 	cDataFile& df = m_world->GetDataFile(filename);
3414 	df.WriteComment("The number of organisms in different bins of shaded altruism");
3415 
3416 	// Cycle through the population -- count the number of altruists in each bin.
3417 	// Also average their shaded donations.
3418 	// Check how many prefer the shaded strategy
3419 
3420 	//int num_shaded_pref = 0; //!num orgs that prefer shaded
3421 	int pop = m_world->GetPopulation().GetSize(); //!the population size for convenience
3422 	int shaded_100 = 0;
3423 	int shaded_90 = 0;
3424 	int shaded_80 = 0;
3425 	int shaded_70 = 0;
3426 	int shaded_60 = 0;
3427 	int shaded_50 = 0;
3428 	int shaded_40 = 0;
3429 	int shaded_30 = 0;
3430 	int shaded_20 = 0;
3431 	int shaded_10 = 0;
3432 	int shaded_0 = 0;
3433 	int total_shaded = 0;
3434 
3435 	//int other_donations = 0;
3436 	int shade_of_gb;
3437 	cOrganism* org;
3438 
3439 
3440 	for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
3441 		shade_of_gb = 0;
3442     cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
3443 		org = cell.GetOrganism();
3444 
3445     if(cell.IsOccupied()) {
3446 			org = cell.GetOrganism();
3447 
3448 			const cInstSet& inst_set = m_world->GetHardwareManager().GetDefaultInstSet();
3449 			const int num_inst = inst_set.GetSize();
3450 			for (int i = 0; i < num_inst; i++) {
3451 				if ((inst_set.GetName(i) == "donate-shadedgb") && (org->GetPhenotype().GetTestCPUInstCount().GetSize() > 0)) {
3452 					shade_of_gb = org->GetPhenotype().GetTestCPUInstCount()[i];
3453 				}
3454 			}
3455 			if (shade_of_gb == 100) shaded_100++;
3456 			if (shade_of_gb > 90) shaded_90++;
3457 			if (shade_of_gb > 80) shaded_80++;
3458 			if (shade_of_gb > 70) shaded_70++;
3459 			if (shade_of_gb > 60) shaded_60++;
3460 			if (shade_of_gb > 50)	shaded_50++;
3461 			if (shade_of_gb > 40)	shaded_40++;
3462 			if (shade_of_gb > 30)	shaded_30++;
3463 			if (shade_of_gb > 20)	shaded_20++;
3464 			if (shade_of_gb > 10)	shaded_10++;
3465 			if (shade_of_gb > 0) shaded_0++;
3466 			total_shaded += shade_of_gb;
3467 		}
3468 	}
3469 
3470 	float high_alt = (float) shaded_90/pop;
3471 	float avg_shade = (float) total_shaded/pop;
3472 
3473 	df.WriteComment("Bins of orgs of shaded strategies.");
3474 	df.WriteTimeStamp();
3475 	df.Write(m_update,   "Update [update]");
3476 	df.Write(pop, "Population [population]");
3477 	df.Write(shaded_100, "shaded-100 [shaded100]");
3478 	df.Write(shaded_90, "shaded-90 [shaded90]");
3479 	df.Write(shaded_80, "shaded-80 [shaded80]");
3480 	df.Write(shaded_70, "shaded-70 [shaded70]");
3481 	df.Write(shaded_60, "shaded-60 [shaded60]");
3482 	df.Write(shaded_50, "shaded-50 [shaded50]");
3483 	df.Write(shaded_40, "shaded-40 [shaded40]");
3484 	df.Write(shaded_30, "shaded-30 [shaded30]");
3485 	df.Write(shaded_20, "shaded-20 [shaded20]");
3486 	df.Write(shaded_10, "shaded-10 [shaded10]");
3487 	df.Write(shaded_0, "shaded-0 [shaded0]");
3488 	df.Write(high_alt, "percent-high-alt  [highalt]");
3489 	df.Write(avg_shade, "avg-shade [avgshade]");
3490 	df.Endl();
3491 
3492 }
3493 
3494 /*
3495  Print data regarding explosions (kazi) and the hamming distances associated with them.
3496  */
PrintKaboom(const cString & filename)3497 void cStats::PrintKaboom(const cString& filename)
3498 {
3499     cDataFile& df = m_world->GetDataFile(filename);
3500     df.WriteComment("The number of kabooms.");
3501 
3502     df.WriteTimeStamp();
3503     df.Write(m_update, "Update [update]");
3504 
3505     df.Write(num_kabooms, "number of kabooms");
3506     df.Write(num_kaboom_kills, "number of orgs killed by kabooms");
3507     df.Write(hd_list, "hamming distances", "");
3508 
3509     df.Endl();
3510     hd_list.ResizeClear(0);
3511     num_kabooms = 0;
3512     num_kaboom_kills=0;
3513 
3514 }
3515 
3516 /*
3517  Print data regarding group formation.
3518  */
PrintGroupsFormedData(const cString & filename)3519 void cStats::PrintGroupsFormedData(const cString& filename)
3520 {
3521 
3522 	cDataFile& df = m_world->GetDataFile(filename);
3523 	df.WriteComment("Information about the groups joined and used by the organisms");
3524 
3525 	map<int,int> groups = m_world->GetPopulation().GetFormedGroups();
3526 
3527 	map <int,int>::iterator itr;
3528 	double avg_size = 0.0;
3529 	double avg_size_wout_empty = 0.0;
3530 	double max_size = 0.0;
3531 	double min_size = 100000000000.0;
3532 	double active_groups = 0.0;
3533 	double groups_per_org = 0.0;
3534 
3535 	for(itr = groups.begin();itr!=groups.end();itr++) {
3536 		double cur_size = itr->second;
3537 		avg_size += cur_size;
3538 		if (cur_size > max_size) max_size = cur_size;
3539 		if (cur_size < min_size) min_size = cur_size;
3540 		if (cur_size > 0) {
3541 			active_groups++;
3542 			avg_size_wout_empty += cur_size;
3543 		}
3544 	}
3545 
3546 	cOrganism* org;
3547 	for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
3548     cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
3549 		org = cell.GetOrganism();
3550 
3551     if(cell.IsOccupied()) {
3552 			org = cell.GetOrganism();
3553 			groups_per_org += org->HasOpinion();
3554 		}
3555 	}
3556 
3557 	avg_size = avg_size / groups.size();
3558 	avg_size_wout_empty = avg_size_wout_empty / active_groups;
3559 	groups_per_org = groups_per_org / m_world->GetPopulation().GetSize();
3560 	df.WriteTimeStamp();
3561 	df.Write(m_update,   "Update [update]");
3562 	df.Write((double)groups.size(), "number of groups [num]");
3563 	df.Write(avg_size, "average size of groups [avgsize]");
3564 	df.Write(avg_size_wout_empty, "average size of  non-emptygroups [avgsizene]");
3565 	df.Write(max_size, "max size of groups [maxsize]");
3566 	df.Write(min_size, "min size of groups [minsize]");
3567 	df.Write(active_groups, "active groups [actgroup]");
3568 	df.Write(groups_per_org, "groups per org life [groupsperorg]");
3569 
3570 
3571 	df.Endl();
3572 
3573 }
3574 
3575 /*
3576  Print data regarding the ids of used groups.
3577  */
PrintGroupIds(const cString & filename)3578 void cStats::PrintGroupIds(const cString& filename)
3579 {
3580 
3581 	cDataFile& df = m_world->GetDataFile(filename);
3582 	df.WriteComment("The ids of groups used.");
3583 
3584 	map<int,int> groups = m_world->GetPopulation().GetFormedGroups();
3585 
3586 	map <int,int>::iterator itr;
3587 
3588 	df.WriteTimeStamp();
3589 
3590 	for(itr = groups.begin();itr!=groups.end();itr++) {
3591 		double cur_size = itr->second;
3592 /*		if (cur_size > 0)*/ {
3593 			df.Write(m_update,   "Update [update]");
3594 			df.Write(itr->first, "group id [groupid]");
3595 			df.Write(cur_size, "size of groups [grsize]");
3596 			df.Endl();
3597 		}
3598 	}
3599 	df.Endl();
3600 }
3601 
3602 // Print data for each group's tolerances.
PrintGroupTolerance(const cString & filename)3603 void cStats::PrintGroupTolerance(const cString& filename)
3604 {
3605   cDataFile& df = m_world->GetDataFile(filename);
3606   df.WriteComment("Group level tolerance data.");
3607   df.WriteTimeStamp();
3608 
3609   map<int, int> groups = m_world->GetPopulation().GetFormedGroups();
3610   map<int, int>::iterator itr;
3611 
3612   for(itr = groups.begin(); itr != groups.end(); itr++) {
3613     double cur_size = itr->second;
3614     int i = itr->first;
3615     df.Write(m_update,                                                  "Update [update]");
3616     df.Write(itr->first,                                                "group id [groupid]");
3617     df.Write(cur_size,                                                  "size of groups [grsize]");
3618     df.Write(resource_count[i],"group resource available [grfood]");
3619     df.Write(resource_count[i] / cur_size, "per capita group resource available [grfoodper]");
3620     if (m_world->GetConfig().TOLERANCE_WINDOW.Get() > 0) {
3621       df.Write(m_world->GetPopulation().CalcGroupOddsImmigrants(i, -1),   "odds for immigrants coming into group [oddsimmigrants]");
3622       df.Write(m_world->GetPopulation().CalcGroupAveImmigrants(i, -1),    "average intra-group tolerance to immigrants [aveimmigrants]");
3623       df.Write(m_world->GetPopulation().CalcGroupSDevImmigrants(i, -1),   "standard deviation for group tolerance to immigrants [sdevimmigrants]");
3624       df.Write(m_world->GetPopulation().CalcGroupOddsOffspring(i),    "odds for offspring being accepted by group [oddsoffspring]");
3625       df.Write(m_world->GetPopulation().CalcGroupAveOthers(i),        "average intra-group tolerance to other offspring being born into group [aveothers]");
3626       df.Write(m_world->GetPopulation().CalcGroupSDevOthers(i),       "standard deviation for group tolerance to other offspring being born into the group [sdevothers]");
3627       df.Write(m_world->GetPopulation().CalcGroupAveOwn(i),           "average intra-group tolerance to individual's own offspring [aveown]");
3628       df.Write(m_world->GetPopulation().CalcGroupSDevOwn(i),          "standard deviation for tolerance to own offspring [sdevown]");
3629     }
3630     df.Endl();
3631   }
3632 }
3633 
PrintGroupMTTolerance(const cString & filename)3634 void cStats::PrintGroupMTTolerance(const cString& filename)
3635 {
3636   cDataFile& df = m_world->GetDataFile(filename);
3637 
3638   df.WriteComment("Group level tolerance data by mating type.");
3639   df.WriteTimeStamp();
3640 
3641   map<int, int> groups = m_world->GetPopulation().GetFormedGroups();
3642   map<int, int>::iterator itr;
3643 
3644   for(itr = groups.begin(); itr != groups.end(); itr++) {
3645     double cur_size = itr->second;
3646     int i = itr->first;
3647     df.Write(m_update,                                                  "Update");
3648     df.Write(itr->first,                                                "group id");
3649     df.Write(cur_size,                                                  "group size");
3650     df.Write(m_world->GetPopulation().NumberGroupFemales(i),            "number group females");
3651     df.Write(m_world->GetPopulation().NumberGroupMales(i),              "number group males");
3652     df.Write(m_world->GetPopulation().NumberGroupJuvs(i),               "number group juvs");
3653     if (m_world->GetConfig().TOLERANCE_WINDOW.Get() > 0) {
3654       df.Write(m_world->GetPopulation().CalcGroupOddsImmigrants(i, 0),   "immigrant female odds");
3655       df.Write(m_world->GetPopulation().CalcGroupAveImmigrants(i, 0),    "ave female-female tolerance");
3656       df.Write(m_world->GetPopulation().CalcGroupSDevImmigrants(i, 0),   "sd female-female tolerance");
3657       df.Write(m_world->GetPopulation().CalcGroupOddsImmigrants(i, 1),   "immigrant male odds");
3658       df.Write(m_world->GetPopulation().CalcGroupAveImmigrants(i, 1),    "ave male-male tolerance");
3659       df.Write(m_world->GetPopulation().CalcGroupSDevImmigrants(i, 1),   "sd male-male tolerance");
3660       df.Write(m_world->GetPopulation().CalcGroupOddsImmigrants(i, 2),   "immigrant juv odds");
3661       df.Write(m_world->GetPopulation().CalcGroupAveImmigrants(i, 2),    "ave juv-juv tolerance");
3662       df.Write(m_world->GetPopulation().CalcGroupSDevImmigrants(i, 2),   "sd juv-juv tolerance");
3663     }
3664     df.Write(resource_count[i],                                         "group resource available");
3665     df.Write(resource_count[i] / cur_size,                              "per capita group resource available");
3666     df.Endl();
3667   }
3668 }
3669 
3670 // Prints number of executions within the update of tolerance instructions executed,
3671 // differentiated between different nop-modifications on each.
PrintToleranceInstructionData(const cString & filename)3672 void cStats::PrintToleranceInstructionData(const cString& filename)
3673 {
3674   const int num_tol_inst = 8;
3675   tArray<cString> m_is_tolerance_inst_names(num_tol_inst);
3676   m_is_tolerance_inst_names[0] = "inc-tolerance_Immigrants";
3677   m_is_tolerance_inst_names[1] = "inc-tolerance_OffspringOwn";
3678   m_is_tolerance_inst_names[2] = "inc-tolerance_OffspringOthers";
3679   m_is_tolerance_inst_names[3] = "dec-tolerance_Immigrants";
3680   m_is_tolerance_inst_names[4] = "dec-tolerance_OffspringOwn";
3681   m_is_tolerance_inst_names[5] = "dec-tolerance_OffspringOthers";
3682   m_is_tolerance_inst_names[6] = "get-tolerance";
3683   m_is_tolerance_inst_names[7] = "get-group-tolerance";
3684 
3685   if (m_is_tolerance_exe_counts.GetSize() != num_tol_inst) m_is_tolerance_exe_counts.Resize(num_tol_inst);
3686 
3687   cDataFile& df = m_world->GetDataFile(filename);
3688 
3689   df.WriteComment("Avida tolerance instruction executions per update");
3690   df.WriteTimeStamp();
3691 
3692   df.Write(m_update, "Update");
3693 
3694   for (int i = 0; i < num_tol_inst; i++) {
3695     df. Write((m_is_tolerance_exe_counts[i].first == m_update) ? m_is_tolerance_exe_counts[i].second : 0 , m_is_tolerance_inst_names[i]);
3696   }
3697 
3698   df.Endl();
3699 }
3700 
3701 // Prints the circumstances around each tolerance instruction executed within the last update.
PrintToleranceData(const cString & filename)3702 void cStats::PrintToleranceData(const cString& filename)
3703 {
3704   // TRACK_TOLERANCE must be on in config for output file to function
3705   if(!m_world->GetConfig().TRACK_TOLERANCE.Get()) {
3706     m_world->GetDriver().RaiseFatalException(-1, "TRACK_TOLERANCE option must be turned on in avida.cfg for PrintToleranceData to function.");
3707   }
3708 
3709   const int num_tol_inst = 8;
3710   tArray<cString> m_is_tolerance_inst_names(num_tol_inst);
3711   m_is_tolerance_inst_names[0] = "inc-tolerance_Immigrants";
3712   m_is_tolerance_inst_names[1] = "inc-tolerance_OffspringOwn";
3713   m_is_tolerance_inst_names[2] = "inc-tolerance_OffspringOthers";
3714   m_is_tolerance_inst_names[3] = "dec-tolerance_Immigrants";
3715   m_is_tolerance_inst_names[4] = "dec-tolerance_OffspringOwn";
3716   m_is_tolerance_inst_names[5] = "dec-tolerance_OffspringOthers";
3717   m_is_tolerance_inst_names[6] = "get-tolerance";
3718   m_is_tolerance_inst_names[7] = "get-group-tolerance";
3719 
3720   cDataFile& df = m_world->GetDataFile(filename);
3721 
3722   df.WriteComment("Avida circumstance data for each tolerance instruction pre-execution");
3723   df.WriteTimeStamp();
3724 
3725   for (int n = 0; n < m_is_tolerance_exe_insts.GetSize(); n++) {
3726     if (m_is_tolerance_exe_insts[n].update == m_update) {
3727       df.Write(m_is_tolerance_exe_insts[n].update, "Update [update]");
3728       df.Write(m_is_tolerance_inst_names[m_is_tolerance_exe_insts[n].inst], "Tolerance instruction [inst]");
3729       df.Write(m_is_tolerance_exe_insts[n].gr_id, "group id [groupid]");
3730       df.Write(m_is_tolerance_exe_insts[n].gr_size, "size of group [grsize]");
3731       df.Write(m_is_tolerance_exe_insts[n].res_level, "group resource available [grfood]");
3732       df.Write(m_is_tolerance_exe_insts[n].odds_immigrants, "odds for immigrants coming into the group [oddsimmigrants]");
3733       df.Write(m_is_tolerance_exe_insts[n].odds_offspring_own, "odds for org's own offspring to stay in group [oddsown]");
3734       df.Write(m_is_tolerance_exe_insts[n].odds_offspring_others, "odds for offspring in group [oddsothers]");
3735       df.Write(m_is_tolerance_exe_insts[n].tol_immigrants, "org's tolerance for immigrants [tol-immi]");
3736       df.Write(m_is_tolerance_exe_insts[n].tol_own, "org's tolerance for own offspring [tol-own]");
3737       df.Write(m_is_tolerance_exe_insts[n].tol_others, "org's tolerance for other offspring in the group [tol-others]");
3738       df.Write(m_is_tolerance_exe_insts[n].tol_max, "tolerance max [tol-max]");
3739       df.Endl();
3740     }
3741   }
3742 }
3743 
PushToleranceInstExe(int tol_inst)3744 void cStats::PushToleranceInstExe(int tol_inst)
3745 {
3746   const int num_tol_inst = 8;
3747   if (m_is_tolerance_exe_counts.GetSize() != num_tol_inst) m_is_tolerance_exe_counts.Resize(num_tol_inst);
3748 
3749   if (m_is_tolerance_exe_counts[tol_inst].first == m_update) {
3750     m_is_tolerance_exe_counts[tol_inst].second++;
3751   } else {
3752     m_is_tolerance_exe_counts[tol_inst].first = m_update;
3753     m_is_tolerance_exe_counts[tol_inst].second = 1;
3754   }
3755 }
3756 
3757 // Adds a record of a tolerance instruction execution w its circumstances.
PushToleranceInstExe(int tol_inst,int group_id,int group_size,double resource_level,double odds_immi,double odds_own,double odds_others,int tol_immi,int tol_own,int tol_others,int tol_max)3758 void cStats::PushToleranceInstExe(int tol_inst, int group_id, int group_size, double resource_level, double odds_immi,
3759           double odds_own, double odds_others, int tol_immi, int tol_own, int tol_others, int tol_max)
3760 {
3761   const int num_tol_inst = 8;
3762   if (m_is_tolerance_exe_counts.GetSize() != num_tol_inst) m_is_tolerance_exe_counts.Resize(num_tol_inst);
3763 
3764   if (m_is_tolerance_exe_insts.GetSize() > 0) {
3765     if (m_is_tolerance_exe_insts[0].update != m_update) {
3766       m_is_tolerance_exe_insts.ResizeClear(0);
3767     }
3768   }
3769 
3770   if (m_is_tolerance_exe_counts[tol_inst].first == m_update) {
3771     m_is_tolerance_exe_counts[tol_inst].second++;
3772   } else {
3773     m_is_tolerance_exe_counts[tol_inst].first = m_update;
3774     m_is_tolerance_exe_counts[tol_inst].second = 1;
3775   }
3776 
3777   s_inst_circumstances tol_circ;
3778   tol_circ.update = m_update;
3779   tol_circ.inst = tol_inst;
3780   tol_circ.gr_id = group_id;
3781   tol_circ.gr_size = group_size;
3782   tol_circ.res_level = resource_level;
3783   tol_circ.odds_immigrants = odds_immi;
3784   tol_circ.odds_offspring_own = odds_own;
3785   tol_circ.odds_offspring_others = odds_others;
3786   tol_circ.tol_immigrants = tol_immi;
3787   tol_circ.tol_own = tol_own;
3788   tol_circ.tol_others = tol_others;
3789   tol_circ.tol_max = tol_max;
3790 
3791   m_is_tolerance_exe_insts.Push(tol_circ);
3792 }
3793 
3794 // Clears all tolerance execution circumstances.
ZeroToleranceInst()3795 void cStats::ZeroToleranceInst()
3796 {
3797   const int num_tol_inst = 8;
3798   for (int i = 0; i < num_tol_inst; i++) {
3799     m_is_tolerance_exe_counts[i] = make_pair(-1,-1);
3800   }
3801   m_is_tolerance_exe_insts.ResizeClear(0);
3802 }
3803 /*
3804  data about donate specific push: id, donated id, kin,
3805  */
3806 
PushDonateSpecificInstExe(int org_id,int cell_id,int recipient_id,int recipient_cell_id,int relatedness,int recip_is_beggar,int num_donates)3807 void cStats::PushDonateSpecificInstExe(int org_id, int cell_id, int recipient_id, int recipient_cell_id, int relatedness, int recip_is_beggar, int num_donates)
3808 {
3809   if (m_donate_specific.GetSize() > 0) {
3810     if (m_donate_specific[0].update != m_update) {
3811       m_donate_specific.ResizeClear(0);
3812     }
3813   }
3814 
3815   sDonateSpecificCircumstances donates;
3816   donates.update = GetUpdate();
3817   donates.org_id = org_id;
3818   donates.cell_id = cell_id;
3819   donates.recipient_id = recipient_id;
3820   donates.recipient_cell_id = recipient_cell_id;
3821   donates.relatedness = relatedness;
3822   donates.recip_is_beggar = recip_is_beggar;
3823   donates.num_donates = num_donates;
3824 
3825   m_donate_specific.Push(donates);
3826 }
3827 
3828 // Prints the circumstances around each tolerance instruction executed within the last update.
PrintDonateSpecificData(const cString & filename)3829 void cStats::PrintDonateSpecificData(const cString& filename)
3830 {
3831   // TRACK_TOLERANCE must be on in config for output file to function
3832   if(!m_world->GetConfig().TRACK_DONATES.Get()) {
3833     m_world->GetDriver().RaiseFatalException(-1, "TRACK_DONATIONS option must be turned on in avida.cfg for PrintDonateSpecificData to function.");
3834   }
3835 
3836   cDataFile& df = m_world->GetDataFile(filename);
3837 
3838   df.WriteComment("Avida circumstance data for each donate-specific instruction pre-execution");
3839   df.WriteTimeStamp();
3840 
3841   for (int i = 0; i < m_donate_specific.GetSize(); i++) {
3842     if (m_donate_specific[i].update == m_update) {
3843       df.Write(m_donate_specific[i].update, "Update [update]");
3844       df.Write(m_donate_specific[i].org_id, "id of donor [org_id]");
3845       df.Write(m_donate_specific[i].cell_id, "cell id of donor [cell_id]");
3846       df.Write(m_donate_specific[i].recipient_id, "id of recipient [recipient_id]");
3847       df.Write(m_donate_specific[i].recipient_cell_id, "cell id of teh recipient [recipient_cell_id]");
3848       df.Write(m_donate_specific[i].relatedness, "relatedness [relatedness]");
3849       df.Write(m_donate_specific[i].recip_is_beggar, "recip_is_beggar [is recipient beggar]");
3850       df.Write(m_donate_specific[i].num_donates, "num_donates [lifetime num donates]");
3851       df.Endl();
3852     }
3853   }
3854 }
3855 /*
3856  Print data regarding the living org targets.
3857  */
PrintTargets(const cString & filename)3858 void cStats::PrintTargets(const cString& filename)
3859 {
3860 	cDataFile& df = m_world->GetDataFile(filename);
3861 	df.WriteComment("Targets in use on update boundary.");
3862   df.WriteComment("-2: is predator, -1: no targets(default), >=0: id of environmental resource targeted).");
3863   df.WriteComment("Format is update + target0 + count0 + target1 + count1 ...");
3864 	df.WriteTimeStamp();
3865 
3866   df.Write(m_update, "Update");
3867 
3868   bool has_pred = false;
3869   int offset = 1;
3870   if (m_world->GetConfig().PRED_PREY_SWITCH.Get() == -2 || m_world->GetConfig().PRED_PREY_SWITCH.Get() > -1) {
3871     has_pred = true;
3872     offset = 2;
3873   }
3874 
3875   // ft's may not be sequentially numbered
3876   bool dec_prey = false;
3877   bool dec_pred = false;
3878   int num_targets = 0;
3879   std::set<int> fts_avail = m_world->GetEnvironment().GetTargetIDs();
3880   set <int>::iterator itr;
3881   for (itr = fts_avail.begin();itr!=fts_avail.end();itr++) {
3882     num_targets++;
3883     if (*itr == -1 && !dec_prey) {
3884       offset--;
3885       dec_prey = true;
3886     }
3887     if (*itr == -2 && !dec_pred) {
3888       offset--;
3889       dec_pred = true;
3890     }
3891   }
3892 
3893   tArray<int> raw_target_list;
3894   raw_target_list.Resize(num_targets);
3895   raw_target_list.SetAll(0);
3896   int this_index = 0;
3897   for (itr = fts_avail.begin(); itr!=fts_avail.end(); itr++) {
3898     raw_target_list[this_index] = *itr;
3899     this_index++;
3900   }
3901 
3902   tArray<int> target_list;
3903   int tot_targets = num_targets + offset;
3904   target_list.Resize(tot_targets);
3905   target_list.SetAll(0);
3906 
3907   target_list[0] = -1;
3908   if (has_pred) {
3909     target_list[0] = -2;
3910     target_list[1] = -1;
3911   }
3912 
3913   for (int i = 0; i < raw_target_list.GetSize(); i++) {
3914     if (raw_target_list[i] >= 0) target_list[i + offset] = raw_target_list[i];
3915   }
3916 
3917   tArray<int> org_targets;
3918   org_targets.Resize(tot_targets);
3919   org_targets.SetAll(0);
3920 
3921   const tSmartArray <cOrganism*> live_orgs = m_world->GetPopulation().GetLiveOrgList();
3922   for (int i = 0; i < live_orgs.GetSize(); i++) {
3923     cOrganism* org = live_orgs[i];
3924     int this_target = org->GetForageTarget();
3925 
3926     int this_index = this_target;
3927     for (int i = 0; i < target_list.GetSize(); i++) {
3928       if (target_list[i] == this_target) {
3929         this_index = i;
3930         break;
3931       }
3932     }
3933     org_targets[this_index]++;
3934   }
3935   for (int target = 0; target < org_targets.GetSize(); target++) {
3936       df.Write(target_list[target], "Target ID");
3937       df.Write(org_targets[target], "Num Orgs Targeting ID");
3938   }
3939   df.Endl();
3940 }
3941 
3942 /*! Track named network stats.
3943  */
NetworkTopology(const network_stats_t & ns)3944 void cStats::NetworkTopology(const network_stats_t& ns) {
3945 	for(network_stats_t::const_iterator i=ns.begin(); i!=ns.end(); ++i) {
3946 		m_network_stats[i->first].Add(i->second);
3947 	}
3948 }
3949 
3950 
3951 /*! Print and reset network statistics.
3952  */
PrintDemeNetworkData(const cString & filename)3953 void cStats::PrintDemeNetworkData(const cString& filename) {
3954   cDataFile& df = m_world->GetDataFile(filename);
3955 
3956   df.WriteComment("Deme network statistics");
3957   df.WriteTimeStamp();
3958 	df.Write(GetUpdate(), "Update [update]");
3959 	for(avg_network_stats_t::iterator i=m_network_stats.begin(); i!=m_network_stats.end(); ++i) {
3960 		df.Write(i->second.Average(), i->first.c_str());
3961 	}
3962 	df.Endl();
3963 	m_network_stats.clear();
3964 }
3965 
PrintDemeNetworkTopology(const cString & filename)3966 void cStats::PrintDemeNetworkTopology(const cString& filename) {
3967   cDataFile& df = m_world->GetDataFile(filename);
3968   df.WriteComment("Deme network topologies.");
3969   df.WriteTimeStamp();
3970 
3971 	for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
3972 		m_world->GetPopulation().GetDeme(i).GetNetwork().PrintTopology(df);
3973 	}
3974 }
3975 
3976 
3977 /*! Called when an organism metabolizes a genome fragment.
3978  */
GenomeFragmentMetabolized(cOrganism * organism,const Sequence & fragment)3979 void cStats::GenomeFragmentMetabolized(cOrganism* organism, const Sequence& fragment) {
3980 	m_hgt_metabolized.Add(fragment.GetSize());
3981 }
3982 
3983 /*! Called when a fragment is inserted into an offspring's genome via HGT.
3984  */
GenomeFragmentInserted(cOrganism * organism,const Sequence & fragment,const cGenomeUtil::substring_match & location)3985 void cStats::GenomeFragmentInserted(cOrganism* organism, const Sequence& fragment, const cGenomeUtil::substring_match& location) {
3986 	m_hgt_inserted.Add(fragment.GetSize());
3987 }
3988 
3989 /*!	Print HGT statistics.
3990  */
PrintHGTData(const cString & filename)3991 void cStats::PrintHGTData(const cString& filename) {
3992   cDataFile& df = m_world->GetDataFile(filename);
3993 
3994   df.WriteComment("Horizontal gene transfer statistics");
3995   df.WriteTimeStamp();
3996 	df.Write(GetUpdate(), "Update [update]");
3997 	df.Write(m_hgt_metabolized.Count(), "Total count of metabolized genome fragments [metcount]");
3998 	df.Write(m_hgt_metabolized.Sum(), "Total size of metabolized genome fragments [metsize]");
3999 	df.Write(m_hgt_inserted.Count(), "Total count of insertion events [inscount]");
4000 	df.Write(m_hgt_inserted.Sum(), "Total size of insertion events [inssize]");
4001 	df.Endl();
4002 
4003 	m_hgt_metabolized.Clear();
4004 	m_hgt_inserted.Clear();
4005 }
4006 
4007 
4008 /*! Log a message.
4009  */
LogMessage(const cOrgMessage & msg,bool dropped,bool lost)4010 void cStats::LogMessage(const cOrgMessage& msg, bool dropped, bool lost) {
4011 	m_message_log.push_back(message_log_entry_t(GetUpdate(),
4012       msg.GetSender()->GetDeme()->GetID(),
4013       msg.GetSenderCellID(),
4014       msg.GetReceiverCellID(),
4015       msg.GetTransCellID(),
4016       msg.GetData(),
4017       msg.GetLabel(),
4018       dropped,
4019       lost));
4020 }
4021 
4022 /*! Prints logged messages.
4023  */
PrintMessageLog(const cString & filename)4024 void cStats::PrintMessageLog(const cString& filename) {
4025 	cDataFile& df = m_world->GetDataFile(filename);
4026 
4027 	df.WriteComment("Log of all messages sent in population.");
4028   df.WriteTimeStamp();
4029 
4030 	for(message_log_t::iterator i=m_message_log.begin(); i!=m_message_log.end(); ++i) {
4031 		df.Write(i->update, "Update [update]");
4032 		df.Write(i->deme, "Deme ID [deme]");
4033 		df.Write(i->src_cell, "Source [src]");
4034 		df.Write(i->dst_cell, "Destination [dst]");
4035         df.Write(i->transmit_cell, "Transmission_cell [trs]");
4036 		df.Write(i->msg_data, "Message data [data]");
4037 		df.Write(i->msg_label, "Message label [label]");
4038 		df.Write(i->dropped, "Dropped [dropped]");
4039 		df.Write(i->lost, "Lost [lost]");
4040 		df.Endl();
4041 	}
4042 
4043 	m_message_log.clear();
4044 }
4045 
4046 
4047 /* Add that an organism performed a task at a certain age */
AgeTaskEvent(int org_id,int task_id,int org_age)4048 void cStats::AgeTaskEvent(int org_id, int task_id, int org_age) {
4049 	reaction_age_map[task_id].Add(org_age);
4050 }
4051 
4052 /* Add the time between two tasks */
AddTaskSwitchTime(int t1,int t2,int time)4053 void cStats::AddTaskSwitchTime(int t1, int t2, int time) {
4054   intrinsic_task_switch_time[make_pair(t1, t2)].Add(time);
4055 }
4056 
4057 
4058 /* Track the relationship between the age of the organism and the task that they perform */
4059 
PrintIntrinsicTaskSwitchingCostData(const cString & filename)4060 void cStats::PrintIntrinsicTaskSwitchingCostData(const cString& filename) {
4061 	cDataFile& df = m_world->GetDataFile(filename);
4062   std::map<std::pair<int, int>, cDoubleSum>::iterator iter;
4063 
4064   df.WriteComment("Number of cyles it takes to change between tasks");
4065   df.WriteTimeStamp();
4066 	df.WriteColumnDesc("Update [update]");
4067   df.WriteColumnDesc("Task 1 [t1]");
4068   df.WriteColumnDesc("Task 2 [t2]");
4069   df.WriteColumnDesc("Mean cycles [mc]");
4070 
4071 
4072   for (iter=intrinsic_task_switch_time.begin(); iter!=intrinsic_task_switch_time.end(); ++iter) {
4073     df.Write(m_update,   "Update [update]");
4074     df.Write(iter->first.first,   "Task 1 [t1]");
4075     df.Write(iter->first.second,   "Task 2 [t2]");
4076     df.Write(iter->second.Average(),   "Mean cycles [mc]");
4077     iter->second.Clear();
4078     df.Endl();
4079   }
4080   intrinsic_task_switch_time.clear();
4081 }
4082 
4083 
4084 /* Track the relationship between the age of the organism and the task that they perform */
4085 
PrintAgePolyethismData(const cString & filename)4086 void cStats::PrintAgePolyethismData(const cString& filename) {
4087 	cDataFile& df = m_world->GetDataFile(filename);
4088 	const cEnvironment& env = m_world->GetEnvironment();
4089   const int num_tasks = env.GetNumTasks();
4090 
4091   df.WriteComment("Tasks, mean organism age, and variance of ages");
4092   df.WriteTimeStamp();
4093 	df.WriteColumnDesc("Update [update]");
4094 	for(int i = 0; i < num_tasks; i++) {
4095 		string s;
4096 		std::stringstream out;
4097 		out << i;
4098 		s = out.str();
4099 		string av_comment = "Task " + s + " Organism Age Mean [meanorgage" + s + "]";
4100 		string err_comment = "Task " + s + " Organism Age Standard Error [errorgage" + s + "]";
4101 		df.WriteColumnDesc(av_comment.c_str());
4102 		df.WriteColumnDesc(err_comment.c_str());
4103 
4104 	}
4105 
4106 	df.FlushComments();
4107 	df.Write(m_update,   "Update");
4108 	for(int i = 0; i < num_tasks; i++) {
4109 		string s;
4110 		std::stringstream out;
4111 		out << i;
4112 		s = out.str();
4113 
4114 		string av_comment = "Task " + s + " Organism Age Mean [meanorgage" + s + "]";
4115 		string err_comment = "Task " + s + " Organism Age Standard Error [errorgage" + s + "]";
4116 		if (reaction_age_map[i].Count()  > 0) {
4117 			df.Write(reaction_age_map[i].Average(), av_comment.c_str());
4118 			df.Write(reaction_age_map[i].StdError(), err_comment.c_str());
4119 		} else {
4120 			df.Write(0, av_comment.c_str());
4121 			df.Write(0, err_comment.c_str());
4122 		}
4123 
4124 		reaction_age_map[i].Clear();
4125 	}
4126 	df.Endl();
4127 }
4128 
4129 
PrintDenData(const cString & filename)4130 void cStats::PrintDenData(const cString& filename) {
4131   if (m_world->GetConfig().USE_AVATARS.Get() <= 0) return;
4132 
4133   int juv_age = m_world->GetConfig().JUV_PERIOD.Get();
4134 
4135   const cResourceLib& resource_lib = m_world->GetEnvironment().GetResourceLib();
4136 
4137   int num_juvs = 0;
4138   int num_adults = 0;
4139   int num_guards = 0;
4140 
4141   int population_size = m_world->GetPopulation().GetSize();
4142 
4143   int num_loiterers = 0;
4144   int active_dens = 0;
4145 
4146 
4147   for (int i = 0; i < m_world->GetPopulation().GetSize(); i++) {
4148     cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
4149     if (!cell.HasAV()) continue;
4150 
4151     tArray<double> cell_res;
4152     cell_res = m_world->GetPopulation().GetCellResources(i, m_world->GetDefaultContext());
4153 
4154     bool is_active = false;
4155     for (int j = 0; j < cell_res.GetSize(); j++) {
4156       if ((resource_lib.GetResource(j)->GetHabitat() == 4 || resource_lib.GetResource(j)->GetHabitat() == 3) && cell_res[j] > 0) {
4157         tArray<cOrganism*> cell_avs = cell.GetCellAVs();
4158         for (int k = 0; k < cell_avs.GetSize(); k++) {
4159           if (cell_avs[k]->GetPhenotype().GetTimeUsed() < juv_age) {
4160             num_juvs++;
4161             is_active = true;
4162           }
4163           else
4164           {
4165             num_adults++;
4166             if (cell_avs[k]->IsGuard()) num_guards++;
4167             else num_loiterers++;
4168           }
4169         }
4170         active_dens += (int)is_active;
4171         break;  // only do this once if two dens overlap
4172       }
4173     }
4174   }
4175     double percent_juv_guard;
4176     double percent_juv_pop;
4177     double percent_guards_pop;
4178 
4179     if (num_guards > 0){
4180         percent_juv_guard = (double)num_juvs/(double)num_guards;
4181     } else {
4182         percent_juv_guard = 0;
4183     }
4184     if (population_size > 0){
4185         percent_juv_pop = (double)num_juvs/(double)population_size;
4186         percent_guards_pop = (double)num_guards/(double)population_size;
4187     } else {
4188         percent_juv_pop = 0;
4189         percent_guards_pop = 0;
4190     }
4191 
4192 
4193   cDataFile& df = m_world->GetDataFile(filename);
4194   df.WriteComment("Number of juveniles and adults in dens");
4195   df.WriteTimeStamp();
4196 	df.WriteColumnDesc("Update [update]");
4197   df.WriteColumnDesc("ActiveDens [active_dens]");
4198   df.WriteColumnDesc("Juveniles [juveniles]");
4199 	df.WriteColumnDesc("Adults [adults]");
4200     df.WriteColumnDesc("Guards [guards]");
4201 	df.WriteColumnDesc("Loiterers [loiterers]");
4202 
4203     df.WriteColumnDesc("Juveniles Killed [juveniles killed]");
4204     df.WriteColumnDesc("Ratio of Juveniles to Guards [percent juvs to guards]");
4205     df.WriteColumnDesc("Ratio of Juveniles to Population [percent juvs to pop]");
4206     df.WriteColumnDesc("Ratio of Guards to Population [percent guards to pop]");
4207 
4208 
4209   df.FlushComments();
4210 
4211     df.Write(m_update,   "Update");
4212       df.Write(active_dens,      "ActiveDens");
4213     df.Write(num_juvs,      "Juveniles");
4214 	df.Write(num_adults,    "Adults");
4215 	df.Write(num_guards,    "Guards");
4216 	df.Write(num_loiterers, "Loiterers");
4217     df.Write(juv_killed, "Juveniles Killed");
4218     df.Write(percent_juv_guard, "Ratio of Juveniles to Guards");
4219     df.Write(percent_juv_pop, "Ratio of Juveniles to Population");
4220     df.Write(percent_guards_pop, "Ratio of Guards to Population");
4221 
4222 
4223 	df.Endl();
4224 
4225 }
4226 
4227 
4228 
4229 
4230 /*! Print statistics related to the diversity of reactions performed by a deme
4231  prior to replication.  */
PrintDemeReactionDiversityReplicationData(const cString & filename)4232 void cStats::PrintDemeReactionDiversityReplicationData(const cString& filename)
4233 {
4234   cDataFile& df = m_world->GetDataFile(filename);
4235 
4236   df.WriteComment("Avida deme reaction diversity replication data");
4237   df.WriteTimeStamp();
4238   df.Write(GetUpdate(), "Update [update]");
4239 
4240 	while(m_switching.size()>100) {
4241 		m_switching.pop_front();
4242 	}
4243 	while(m_deme_diversity.size()>100) {
4244 		m_deme_diversity.pop_front();
4245 	}
4246 	while(m_shannon_div.size()>100) {
4247 		m_shannon_div.pop_front();
4248 	}
4249 	while(m_num_orgs_perf_reaction.size() > 100) {
4250 		m_num_orgs_perf_reaction.pop_front();
4251 	}
4252   while (m_shannon_div_norm.size() > 100) {
4253 		m_shannon_div_norm.pop_front();
4254   }
4255   while (m_percent_reproductives.size() > 100) {
4256 		m_percent_reproductives.pop_front();
4257   }
4258 
4259 	if(m_deme_diversity.empty()) {
4260 		df.Write(0.0, "Mean number of different reactions by deme [demereact]");
4261 	} else {
4262 		df.Write(std::accumulate(m_deme_diversity.begin(), m_deme_diversity.end(), 0.0)/m_deme_diversity.size(), "Mean number of different reactions by deme [demereact]");
4263 	}
4264 	if(m_switching.empty()) {
4265 		df.Write(0.0, "Mean number of deme switch penalties per org  [orgpen]");
4266 	} else {
4267 		df.Write(std::accumulate(m_switching.begin(), m_switching.end(), 0.0)/m_switching.size(), "Mean number of deme switch penalties per org  [orgpen]");
4268 	}
4269 	if(m_shannon_div.empty()) {
4270 		df.Write(0.0, "Mean shannon mutual information per deme [shannon]");
4271 	} else {
4272 		df.Write(std::accumulate(m_shannon_div.begin(), m_shannon_div.end(), 0.0)/m_shannon_div.size(), "Mean shannon mutual entropy [shannon]");
4273 	}
4274   if(m_shannon_div_norm.empty()) {
4275 		df.Write(0.0, "Mean shannon normalized mutual information per deme [shannonnorm]");
4276 	} else {
4277 		df.Write(std::accumulate(m_shannon_div_norm.begin(), m_shannon_div_norm.end(), 0.0)/m_shannon_div_norm.size(), "Mean shannon normalalized mutual information [shannonnorm]");
4278 	}
4279 	if(m_num_orgs_perf_reaction.empty()) {
4280 		df.Write(0.0, "Mean number of orgs that perform a reaction [meanreact]");
4281 	} else {
4282 		df.Write(std::accumulate(m_num_orgs_perf_reaction.begin(), m_num_orgs_perf_reaction.end(), 0.0)/m_num_orgs_perf_reaction.size(), "Mean number of orgs that perform a reaction [meanreact]");
4283 	}
4284   if(m_percent_reproductives.empty()) {
4285 		df.Write(0.0, "Mean percent of orgs that replicate [meanperrepros]");
4286 	} else {
4287 		df.Write(std::accumulate(m_percent_reproductives.begin(), m_percent_reproductives.end(), 0.0)/m_percent_reproductives.size(), "Mean percent of orgs that replicate [meanperrepros]");
4288 	}
4289 
4290 
4291   df.Endl();
4292 }
4293 
4294 /*! Print statistics related to the amount of resources amassed by the deme,
4295  as well as germ/soma information */
PrintDemeGermResourcesData(const cString & filename)4296 void cStats::PrintDemeGermResourcesData(const cString& filename)
4297 {
4298   cDataFile& df = m_world->GetDataFile(filename);
4299 
4300   int deme_id = 0;
4301   double deme_res = m_world->GetPopulation().GetDeme(deme_id).GetTotalResourceAmountConsumed();
4302 
4303   if (deme_res > m_resource_print_thresh) {
4304 
4305     // update thresh
4306     m_resource_print_thresh += m_world->GetConfig().RES_FOR_DEME_REP.Get();
4307 
4308     df.WriteComment("Avida deme germ/soma and resources amassed data");
4309     df.WriteTimeStamp();
4310     df.Write(GetUpdate(), "Update [update]");
4311     df.Write(deme_res, "Mean amount of resources consumed");
4312 
4313     std::pair<double, double> p = m_world->GetPopulation().GetDeme(deme_id).GetGermlineNumPercent();
4314     df.Write(p.first, "Mean number of organisms flagged as germ");
4315     df.Write(p.second, "Mean percent of organisms flagged as germ");
4316 
4317     p = m_world->GetPopulation().GetDeme(deme_id).GetAveVarWorkLoad();
4318     df.Write(p.first, "Mean workload of organisms");
4319 
4320 
4321     df.Endl();
4322   }
4323 
4324 }
4325 
4326 
4327 /*! Prints the genotype ids of all organisms within the maximally-fit deme.
4328  */
PrintWinningDeme(const cString & filename)4329 void cStats::PrintWinningDeme(const cString& filename)
4330 {
4331   cDataFile& df = m_world->GetDataFile(filename);
4332   df.WriteComment("Genotype IDs of the constituent organisms within each deme.");
4333   df.WriteTimeStamp();
4334   df.WriteColumnDesc("Update [update]");
4335   df.WriteColumnDesc("Deme id [demeid]");
4336   df.WriteColumnDesc("Deme fitness [fitness]");
4337   df.WriteColumnDesc("Number of unique genomes in deme [uniq]");
4338   df.WriteColumnDesc("Genome ID [genomeids]");
4339   df.FlushComments();
4340 
4341   std::pair<int, double> max_element = std::make_pair(0, 0.0);
4342   bool found_max = false;
4343   for (int i=0; i<(int)m_deme_fitness.size(); ++i) {
4344     if (m_deme_fitness[i] > max_element.second) {
4345       max_element.first = i;
4346       max_element.second = m_deme_fitness[i];
4347       found_max = true;
4348     }
4349   }
4350 
4351   if(!found_max) {
4352     return;
4353   }
4354 
4355   df.WriteAnonymous(GetUpdate());
4356   df.WriteAnonymous(max_element.first);
4357   df.WriteAnonymous(max_element.second);
4358 
4359   cDeme& deme = m_world->GetPopulation().GetDeme(max_element.first);
4360 
4361   std::set<int> uniq;
4362   std::vector<int> genotypes;
4363 
4364   for(int i=0; i<deme.GetSize(); ++i) {
4365     cOrganism* org=deme.GetOrganism(i);
4366     if(org != 0) {
4367       genotypes.push_back(org->GetBioGroup("genotype")->GetID());
4368       uniq.insert(org->GetBioGroup("genotype")->GetID());
4369     }
4370   }
4371 
4372   df.WriteAnonymous((int)uniq.size());
4373 
4374   for(int i=0; i<(int)genotypes.size(); ++i) {
4375     df.WriteAnonymous(genotypes[i]);
4376   }
4377   df.Endl();
4378 }
4379 
4380 
4381 /*! Record information about an organism migrating from this population.
4382  */
OutgoingMigrant(const cOrganism * org)4383 void cStats::OutgoingMigrant(const cOrganism* org) {
4384 	m_outgoing.Add(1);
4385 }
4386 
4387 /*! Record information about an organism migrating into this population.
4388  */
IncomingMigrant(const cOrganism * org)4389 void cStats::IncomingMigrant(const cOrganism* org) {
4390 	m_incoming.Add(1);
4391 }
4392 
4393 /*! Print multiprocess data.
4394  */
PrintMultiProcessData(const cString & filename)4395 void cStats::PrintMultiProcessData(const cString& filename) {
4396 	cDataFile& df = m_world->GetDataFile(filename);
4397 
4398   df.WriteComment("Avida-MP data");
4399   df.WriteTimeStamp();
4400   df.Write(GetUpdate(), "Update [update]");
4401 	df.Write(m_outgoing.Count(), "Outgoing migrants [outgoing]");
4402 	df.Write(m_incoming.Count(), "Incoming migrants [incoming]");
4403 	df.Endl();
4404 
4405 	m_outgoing.Clear();
4406 	m_incoming.Clear();
4407 }
4408 
4409 /*! Track profiling data.
4410  */
ProfilingData(const profiling_stats_t & pf)4411 void cStats::ProfilingData(const profiling_stats_t& pf) {
4412 	for(profiling_stats_t::const_iterator i=pf.begin(); i!=pf.end(); ++i) {
4413 		m_profiling[i->first].Add(i->second);
4414 	}
4415 }
4416 
4417 /*! Print profiling data.
4418  */
PrintProfilingData(const cString & filename)4419 void cStats::PrintProfilingData(const cString& filename) {
4420 	cDataFile& df = m_world->GetDataFile(filename);
4421 
4422   df.WriteComment("Profiling statistics");
4423   df.WriteTimeStamp();
4424 	df.Write(GetUpdate(), "Update [update]");
4425 
4426 	for(avg_profiling_stats_t::iterator i=m_profiling.begin(); i!=m_profiling.end(); ++i) {
4427 		df.Write(i->second.Average(), i->first.c_str());
4428 	}
4429 	df.Endl();
4430 
4431 	m_profiling.clear();
4432 }
4433 
4434 /*! Print organism location.
4435 */
PrintOrganismLocation(const cString & filename)4436 void cStats::PrintOrganismLocation(const cString& filename) {
4437 	cDataFile& df = m_world->GetDataFile(filename);
4438 
4439   df.WriteComment("Organism location data");
4440   df.WriteTimeStamp();
4441 
4442 	for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
4443 		cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
4444 		if(cell.IsOccupied()) {
4445 			df.Write(GetUpdate(), "Update [update]");
4446 			df.Write(i, "Cell ID [cellid]");
4447 			df.Write(cell.GetOrganism()->GetID(), "Organism ID [orgid]");
4448 			df.Endl();
4449 		}
4450 	}
4451 }
4452 
4453 // Records information about mates that are chosen from the birth chamber
RecordSuccessfulMate(cBirthEntry & successful_mate,cBirthEntry & chooser)4454 void cStats::RecordSuccessfulMate(cBirthEntry& successful_mate, cBirthEntry& chooser) {
4455   //Check if we need to resize the array of successful mates, and re-size it if needed
4456   int array_size = m_successful_mates.GetSize();
4457   if (array_size <= m_num_successful_mates) {
4458     m_successful_mates.Resize(m_num_successful_mates + 1);
4459     m_choosers.Resize(m_num_successful_mates + 1);
4460   }
4461 
4462   m_successful_mates[m_num_successful_mates] = successful_mate;
4463   m_choosers[m_num_successful_mates] = chooser;
4464 
4465   m_num_successful_mates++;
4466 }
4467 
4468 // Records information about mates that are chosen from the birth chamber
PrintSuccessfulMates(cString & filename)4469 void cStats::PrintSuccessfulMates(cString& filename) {
4470   cDataFile& df = m_world->GetDataFile(filename);
4471   df.WriteTimeStamp();
4472   df.WriteComment("First half of each line gives information about the 'chosen' mate");
4473   df.WriteComment("Second half of each line gives information about the 'chooser'");
4474   df.WriteComment(cBirthEntry::GetPhenotypeStringFormat());
4475   df.Endl();
4476   std::ofstream& df_stream = df.GetOFStream();
4477   for (int i = 0; i < m_num_successful_mates; i++) {
4478     df_stream << m_successful_mates[i].GetPhenotypeString() << " " << m_choosers[i].GetPhenotypeString() << endl;
4479   }
4480   m_world->GetDataFileManager().Remove(filename);
4481 }
4482 
4483 //Prints out average data only for the males in the population (MATING_TYPES option should be turned on)
PrintMaleAverageData(const cString & filename)4484 void cStats::PrintMaleAverageData(const cString& filename)
4485 {
4486   cDataFile& df = m_world->GetDataFile(filename);
4487 
4488   df.WriteComment("Male Average Data");
4489   df.WriteTimeStamp();
4490 
4491   df.Write(m_update,                          "Update");
4492   df.Write(sum_male_fitness.Average(),        "Fitness");
4493   df.Write(sum_male_gestation.Average(),      "Gestation Time");
4494   df.Write(sum_male_merit.Average(),          "Merit");
4495   df.Write(sum_male_creature_age.Average(),   "Creature Age");
4496   df.Write(sum_male_generation.Average(),     "Generation");
4497   df.Write(sum_male_size.Average(),           "Genome Length");
4498 
4499   df.Endl();
4500 }
4501 
4502 //Prints out average data only for the females in the population (MATING_TYPES option should be turned on)
PrintFemaleAverageData(const cString & filename)4503 void cStats::PrintFemaleAverageData(const cString& filename)
4504 {
4505   cDataFile& df = m_world->GetDataFile(filename);
4506 
4507   df.WriteComment("Female Average Data");
4508   df.WriteTimeStamp();
4509 
4510   df.Write(m_update,                          "Update");
4511   df.Write(sum_female_fitness.Average(),        "Fitness");
4512   df.Write(sum_female_gestation.Average(),      "Gestation Time");
4513   df.Write(sum_female_merit.Average(),          "Merit");
4514   df.Write(sum_female_creature_age.Average(),   "Creature Age");
4515   df.Write(sum_female_generation.Average(),     "Generation");
4516   df.Write(sum_female_size.Average(),           "Genome Length");
4517 
4518   df.Endl();
4519 }
4520 
PrintMaleErrorData(const cString & filename)4521 void cStats::PrintMaleErrorData(const cString& filename)
4522 {
4523   cDataFile& df = m_world->GetDataFile(filename);
4524 
4525   df.WriteComment("Male Standard Error Data");
4526   df.WriteTimeStamp();
4527 
4528   df.Write(m_update,                          "Update");
4529   df.Write(sum_male_fitness.StdError(),        "Fitness");
4530   df.Write(sum_male_gestation.StdError(),      "Gestation Time");
4531   df.Write(sum_male_merit.StdError(),          "Merit");
4532   df.Write(sum_male_creature_age.StdError(),   "Creature Age");
4533   df.Write(sum_male_generation.StdError(),     "Generation");
4534   df.Write(sum_male_size.StdError(),           "Genome Length");
4535 
4536   df.Endl();
4537 }
4538 
PrintFemaleErrorData(const cString & filename)4539 void cStats::PrintFemaleErrorData(const cString& filename)
4540 {
4541   cDataFile& df = m_world->GetDataFile(filename);
4542 
4543   df.WriteComment("Female Standard Error Data");
4544   df.WriteTimeStamp();
4545 
4546   df.Write(m_update,                          "Update");
4547   df.Write(sum_female_fitness.StdError(),        "Fitness");
4548   df.Write(sum_female_gestation.StdError(),      "Gestation Time");
4549   df.Write(sum_female_merit.StdError(),          "Merit");
4550   df.Write(sum_female_creature_age.StdError(),   "Creature Age");
4551   df.Write(sum_female_generation.StdError(),     "Generation");
4552   df.Write(sum_female_size.StdError(),           "Genome Length");
4553 
4554   df.Endl();
4555 }
4556 
PrintMaleVarianceData(const cString & filename)4557 void cStats::PrintMaleVarianceData(const cString& filename)
4558 {
4559   cDataFile& df = m_world->GetDataFile(filename);
4560 
4561   df.WriteComment("Male Variance Data");
4562   df.WriteTimeStamp();
4563 
4564   df.Write(m_update,                          "Update");
4565   df.Write(sum_male_fitness.Variance(),        "Fitness");
4566   df.Write(sum_male_gestation.Variance(),      "Gestation Time");
4567   df.Write(sum_male_merit.Variance(),          "Merit");
4568   df.Write(sum_male_creature_age.Variance(),   "Creature Age");
4569   df.Write(sum_male_generation.Variance(),     "Generation");
4570   df.Write(sum_male_size.Variance(),           "Genome Length");
4571 
4572   df.Endl();
4573 }
4574 
PrintFemaleVarianceData(const cString & filename)4575 void cStats::PrintFemaleVarianceData(const cString& filename)
4576 {
4577   cDataFile& df = m_world->GetDataFile(filename);
4578 
4579   df.WriteComment("Female Variance Data");
4580   df.WriteTimeStamp();
4581 
4582   df.Write(m_update,                          "Update");
4583   df.Write(sum_female_fitness.Variance(),        "Fitness");
4584   df.Write(sum_female_gestation.Variance(),      "Gestation Time");
4585   df.Write(sum_female_merit.Variance(),          "Merit");
4586   df.Write(sum_female_creature_age.Variance(),   "Creature Age");
4587   df.Write(sum_female_generation.Variance(),     "Generation");
4588   df.Write(sum_female_size.Variance(),           "Genome Length");
4589 
4590   df.Endl();
4591 
4592 }
4593 
PrintMaleInstructionData(const cString & filename,const cString & inst_set)4594 void cStats::PrintMaleInstructionData(const cString& filename, const cString& inst_set)
4595 {
4596   cDataFile& df = m_world->GetDataFile(filename);
4597 
4598   df.WriteComment("Male instruction execution data");
4599   df.WriteTimeStamp();
4600 
4601   df.Write(m_update, "Update");
4602 
4603   for (int i = 0; i < m_is_pred_exe_inst_map[inst_set].GetSize(); i++) {
4604     df.Write(m_is_male_exe_inst_map[inst_set][i].Sum(), m_is_inst_names_map[inst_set][i]);
4605   }
4606 
4607   df.Endl();
4608 }
4609 
PrintFemaleInstructionData(const cString & filename,const cString & inst_set)4610 void cStats::PrintFemaleInstructionData(const cString& filename, const cString& inst_set)
4611 {
4612   cDataFile& df = m_world->GetDataFile(filename);
4613 
4614   df.WriteComment("Female instruction execution data");
4615   df.WriteTimeStamp();
4616 
4617   df.Write(m_update, "Update");
4618 
4619   for (int i = 0; i < m_is_pred_exe_inst_map[inst_set].GetSize(); i++) {
4620     df.Write(m_is_female_exe_inst_map[inst_set][i].Sum(), m_is_inst_names_map[inst_set][i]);
4621   }
4622 
4623   df.Endl();
4624 }
4625 
PrintMiniTraceReactions(cOrganism * org)4626 void cStats::PrintMiniTraceReactions(cOrganism* org)
4627 {
4628   int group_id = m_world->GetConfig().DEFAULT_GROUP.Get();
4629   if (org->HasOpinion()) group_id = org->GetOpinion().first;
4630   cString filename("");
4631   filename.Set("minitraces/trace_reactions/org%d-ud%d-grp%d_ft%d-gt%d.trcreac", org->GetID(), org->GetPhenotype().GetUpdateBorn(), group_id, org->GetForageTarget(), org->GetBioGroup("genotype")->GetID());
4632 
4633   // Open the file...
4634   cDataFile& df = m_world->GetDataFile(filename);
4635 
4636   if (!df.HeaderDone()) {
4637     df.WriteTimeStamp();
4638     df.WriteComment("Reaction Data for Traced Org to Date (death or end)");
4639     df.WriteComment("OrgID");
4640     df.WriteComment("Update Born");
4641     df.WriteComment("Reaction Counts");
4642     df.WriteComment("CPU Cycle at First Trigger of Each Reaction");
4643     df.WriteComment("Exec Count at First Trigger (== index into execution trace and nav traces)");
4644     df.FlushComments();
4645     df.Endl();
4646   }
4647 
4648   std::ofstream& fp = df.GetOFStream();
4649 
4650   tArray<int> reaction_count = org->GetPhenotype().GetCurReactionCount();
4651   tArray<int> reaction_cycles = org->GetPhenotype().GetFirstReactionCycles();
4652   tArray<int> reaction_execs = org->GetPhenotype().GetFirstReactionExecs();
4653 
4654   fp << org->GetID() << " " << org->GetPhenotype().GetUpdateBorn() << " ";
4655   for (int i = 0; i < reaction_count.GetSize() - 1; i++) {
4656     fp << reaction_count[i] << ",";
4657   }
4658   fp << reaction_count[reaction_count.GetSize() - 1] << " ";
4659 
4660   for (int i = 0; i < reaction_cycles.GetSize() - 1; i++) {
4661     fp << reaction_cycles[i] << ",";
4662   }
4663   fp << reaction_cycles[reaction_cycles.GetSize() - 1] << " ";
4664 
4665   for (int i = 0; i < reaction_execs.GetSize() - 1; i++) {
4666     fp << reaction_execs[i] << ",";
4667   }
4668   fp << reaction_execs[reaction_execs.GetSize() - 1];
4669   fp << endl;
4670 
4671   m_world->GetDataFileManager().Remove(filename);
4672 }
4673 
PrintMicroTraces(tSmartArray<char> & exec_trace,int birth_update,int org_id,int ft,int gen_id)4674 void cStats::PrintMicroTraces(tSmartArray<char>& exec_trace, int birth_update, int org_id, int ft, int gen_id)
4675 {
4676   int death_update = GetUpdate();
4677   cDataFile& df = m_world->GetDataFile("microtrace.dat");
4678 
4679   if (!df.HeaderDone()) {
4680     df.WriteComment("Trace Execution Data");
4681     df.WriteTimeStamp();
4682     df.WriteComment("DeathUpdate");
4683     df.WriteComment("BirthUpdate");
4684     df.WriteComment("OrgID");
4685     df.WriteComment("GenotypeID");
4686     df.WriteComment("ForageTarget");
4687     df.Endl();
4688   }
4689 
4690   std::ofstream& fp = df.GetOFStream();
4691   fp << death_update << "," << birth_update << "," << org_id << "," << gen_id << "," << ft << ",";
4692   for (int i = 0; i < exec_trace.GetSize(); i++) {
4693     fp << exec_trace[i];
4694   }
4695   fp << endl;
4696 }
4697 
UpdateTopNavTrace(cOrganism * org)4698 void cStats::UpdateTopNavTrace(cOrganism* org)
4699 {
4700   // 'best' org is the one among the orgs with the highest reaction achieved that reproduced in the least number of cycles
4701   // using cycles, so any inst executions in parallel multi-threads are only counted as one exec
4702   int best_reac = -1;
4703   tArray<int> reaction_count = org->GetPhenotype().GetCurReactionCount();
4704   for (int i = reaction_count.GetSize() -1; i >= 0; i--) {
4705     if (reaction_count[i] > 0) {
4706       best_reac = i;
4707       break;
4708     }
4709   }
4710   int cycle = org->GetPhenotype().GetTimeUsed();
4711   bool new_winner = false;
4712   if (best_reac >= topreac) {
4713     if (best_reac == topreac && cycle < topcycle) new_winner = true;
4714     else if (best_reac > topreac) new_winner = true;
4715   }
4716   if (new_winner) {
4717     topreac = best_reac;
4718     topcycle = cycle;
4719     topgenid = org->GetBioGroup("genotype")->GetID();
4720     topid = org->GetID();
4721 
4722     tSmartArray<char> trace = org->GetHardware().GetMicroTrace();
4723     tSmartArray<int> traceloc = org->GetHardware().GetNavTraceLoc();
4724     tSmartArray<int> tracefacing = org->GetHardware().GetNavTraceFacing();
4725     tSmartArray<int> traceupdate = org->GetHardware().GetNavTraceUpdate();
4726 
4727     toptrace.Resize(trace.GetSize());
4728     topnavtraceloc.Resize(traceloc.GetSize());
4729     topnavtraceloc.SetAll(-1);
4730     topnavtracefacing.Resize(tracefacing.GetSize());
4731     topnavtracefacing.SetAll(-1);
4732     topnavtraceupdate.Resize(traceupdate.GetSize());
4733     topnavtraceupdate.SetAll(-1);
4734 
4735     assert(toptrace.GetSize() == topnavtraceloc.GetSize());
4736     assert(topnavtraceloc.GetSize() == topnavtracefacing.GetSize());
4737     assert(topnavtracefacing.GetSize() == topnavtraceupdate.GetSize());
4738     for (int i = 0; i < toptrace.GetSize(); i++) {
4739       toptrace[i] = trace[i];
4740       topnavtraceloc[i] = traceloc[i];
4741       topnavtracefacing[i] = tracefacing[i];
4742       topnavtraceupdate[i] = traceupdate[i];
4743     }
4744 
4745     tArray<int> reaction_cycles = org->GetPhenotype().GetFirstReactionCycles();
4746     tArray<int> reaction_execs = org->GetPhenotype().GetFirstReactionExecs();
4747 
4748     topreactioncycles.Resize(reaction_cycles.GetSize());
4749     topreactioncycles.SetAll(-1);
4750     topreactionexecs.Resize(reaction_execs.GetSize());
4751     topreactionexecs.SetAll(-1);
4752     topreactions.Resize(reaction_count.GetSize());
4753     topreactions.SetAll(0);
4754 
4755     assert(topreactions.GetSize() == topreactioncycles.GetSize());
4756     assert(topreactioncycles.GetSize() == topreactionexecs.GetSize());
4757     for (int i = 0; i < topreactions.GetSize(); i++) {
4758       topreactions[i] = reaction_count[i];
4759       topreactioncycles[i] = reaction_cycles[i];
4760       topreactionexecs[i] = reaction_execs[i];
4761     }
4762   }
4763   if (m_world->GetPopulation().GetTopNavQ().GetSize() <= 1) PrintTopNavTrace();
4764 }
4765 
PrintTopNavTrace()4766 void cStats::PrintTopNavTrace()
4767 {
4768   cDataFile& df = m_world->GetDataFile("navtrace.dat");
4769 
4770   df.WriteComment("Org That Reproduced the Fastest (fewest cycles) Among Orgs with the Highest Reaction ID");
4771   df.WriteTimeStamp();
4772   df.WriteComment("GenotypeID");
4773   df.WriteComment("OrgID");
4774   df.WriteComment("Cycle at First Reproduction (parallel multithread execs = 1 cycle)");
4775   df.WriteComment("Reaction Counts at First Reproduction");
4776   df.WriteComment("CPU Cycle at First Trigger of Each Reaction");
4777   df.WriteComment("Exec Count at First Trigger (== index into execution trace and nav traces)");
4778   df.WriteComment("");
4779   df.WriteComment("Updates for each entry in each following trace (to match with res data)");
4780   df.WriteComment("CellIDs to First Reproduction");
4781   df.WriteComment("OrgFacings to First Reproduction");
4782   df.WriteComment("Execution Trace to First Reproduction");
4783   df.Endl();
4784 
4785   std::ofstream& fp = df.GetOFStream();
4786 
4787   if (topreactions.GetSize()) {
4788     fp << topgenid << " " << topid << " " << topcycle << " ";
4789     // reaction related
4790     for (int i = 0; i < topreactions.GetSize() - 1; i++) {
4791       fp << topreactions[i] << ",";
4792     }
4793     fp << topreactions[topreactions.GetSize() - 1] << " ";
4794 
4795     for (int i = 0; i < topreactioncycles.GetSize() - 1; i++) {
4796       fp << topreactioncycles[i] << ",";
4797     }
4798     fp << topreactioncycles[topreactioncycles.GetSize() - 1] << " ";
4799 
4800     for (int i = 0; i < topreactionexecs.GetSize() - 1; i++) {
4801       fp << topreactionexecs[i] << ",";
4802     }
4803     fp << topreactionexecs[topreactionexecs.GetSize() - 1] << " ";
4804 
4805     // instruction exec sequence related (printed in reverse order to get firs exec as first printed)
4806     for (int i = 0; i < topnavtraceupdate.GetSize() - 1; i++) {
4807       fp << topnavtraceupdate[i] << ",";
4808     }
4809     fp << topnavtraceupdate[topnavtraceupdate.GetSize() - 1] << " ";
4810 
4811     for (int i = 0; i < topnavtraceloc.GetSize() - 1; i++) {
4812       fp << topnavtraceloc[i] << ",";
4813     }
4814     fp << topnavtraceloc[topnavtraceloc.GetSize() - 1] << " ";
4815 
4816     for (int i = 0; i < topnavtracefacing.GetSize() - 1; i++) {
4817       fp << topnavtracefacing[i] << ",";
4818     }
4819     fp << topnavtracefacing[topnavtracefacing.GetSize() - 1] << " ";
4820 
4821     for (int i = 0; i < toptrace.GetSize(); i++) {
4822       fp << toptrace[i];
4823     }
4824     fp << endl;
4825   }
4826 }
4827 
PrintReproData(cOrganism * org)4828 void cStats::PrintReproData(cOrganism* org)
4829 {
4830   int update = GetUpdate();
4831   cDataFile& df = m_world->GetDataFile("repro_data.dat");
4832 
4833   if (!df.HeaderDone()) {
4834     df.WriteComment("Org Data up to First Reproduction");
4835     df.WriteTimeStamp();
4836     df.WriteComment("ReproUpdate");
4837     df.WriteComment("GenotypeID");
4838     df.WriteComment("OrgID");
4839     df.WriteComment("Age (updates)");
4840     df.WriteComment("TimeUsed (cycles)");
4841     df.WriteComment("NumExecutions (attempted executions)");
4842     df.WriteComment("ReactionCounts");
4843     df.Endl();
4844   }
4845 
4846   std::ofstream& fp = df.GetOFStream();
4847   fp << update << " " << org->GetBioGroup("genotype")->GetID()<< " " << org->GetID() << " " << org->GetPhenotype().GetAge() << " " << org->GetPhenotype().GetTimeUsed()
4848       << " " << org->GetPhenotype().GetNumExecs() << " ";
4849   tArray<int> reaction_count = org->GetPhenotype().GetCurReactionCount();
4850   for (int i = 0; i < reaction_count.GetSize() - 1; i++) {
4851     fp << reaction_count[i] << ",";
4852   }
4853   fp << reaction_count[reaction_count.GetSize() - 1] << endl;
4854 }
4855