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