1 /*
2  *  cDefaultRunDriver.cc
3  *  Avida
4  *
5  *  Created by David on 12/11/05.
6  *  Copyright 1999-2011 Michigan State University. All rights reserved.
7  *
8  *
9  *  This file is part of Avida.
10  *
11  *  Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
12  *  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
13  *
14  *  Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License along with Avida.
18  *  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include "cDefaultRunDriver.h"
23 
24 #include "cAvidaContext.h"
25 #include "cBGGenotype.h"
26 #include "cClassificationManager.h"
27 #include "cHardwareBase.h"
28 #include "cHardwareManager.h"
29 #include "cOrganism.h"
30 #include "cPopulation.h"
31 #include "cPopulationCell.h"
32 #include "cStats.h"
33 #include "cString.h"
34 #include "cWorld.h"
35 
36 #include <cstdlib>
37 #include <ctime>
38 #include <iostream>
39 #include <iomanip>
40 
41 using namespace std;
42 
43 
cDefaultRunDriver(cWorld * world)44 cDefaultRunDriver::cDefaultRunDriver(cWorld* world) : m_world(world), m_done(false),
45 m_fastforward(false),m_last_generation(0),  m_generation_same_update_count(0)
46 {
47   GlobalObjectManager::Register(this);
48   world->SetDriver(this);
49 
50   // Save this config variable
51   m_generation_update_fastforward_threshold = m_world->GetConfig().FASTFORWARD_UPDATES.Get();
52   m_population_fastforward_threshold = m_world->GetConfig().FASTFORWARD_NUM_ORGS.Get();
53 }
54 
~cDefaultRunDriver()55 cDefaultRunDriver::~cDefaultRunDriver()
56 {
57   GlobalObjectManager::Unregister(this);
58   delete m_world;
59 }
60 
61 
Run()62 void cDefaultRunDriver::Run()
63 {
64   cPopulation& population = m_world->GetPopulation();
65   cStats& stats = m_world->GetStats();
66 
67   const double point_mut_prob = m_world->GetConfig().POINT_MUT_PROB.Get() +
68                                 m_world->GetConfig().POINT_INS_PROB.Get() +
69                                 m_world->GetConfig().POINT_DEL_PROB.Get() +
70                                 m_world->GetConfig().DIV_LGT_PROB.Get();
71 
72   void (cPopulation::*ActiveProcessStep)(cAvidaContext& ctx, double step_size, int cell_id) = &cPopulation::ProcessStep;
73   if (m_world->GetConfig().SPECULATIVE.Get() &&
74       m_world->GetConfig().THREAD_SLICING_METHOD.Get() != 1 && !m_world->GetConfig().IMPLICIT_REPRO_END.Get() && point_mut_prob == 0.0) {
75     ActiveProcessStep = &cPopulation::ProcessStepSpeculative;
76   }
77 
78   cAvidaContext& ctx = m_world->GetDefaultContext();
79 
80   while (!m_done) {
81     m_world->GetEvents(ctx);
82     if(m_done == true) break;
83 
84     // Increment the Update.
85     stats.IncCurrentUpdate();
86 
87     population.ProcessPreUpdate();
88 
89     // Handle all data collection for previous update.
90     if (stats.GetUpdate() > 0) {
91       // Tell the stats object to do update calculations and printing.
92       stats.ProcessUpdate();
93     }
94 
95     // don't process organisms if we are in fast-forward mode. -- @JEB
96     if (!GetFastForward()) {
97       // Process the update.
98 			// query the world to calculate the exact size of this update:
99       const int UD_size = m_world->CalculateUpdateSize();
100       const double step_size = 1.0 / (double) UD_size;
101 
102       for (int i = 0; i < UD_size; i++) {
103         if(population.GetNumOrganisms() == 0) {
104           break;
105         }
106         (population.*ActiveProcessStep)(ctx, step_size, population.ScheduleOrganism());
107       }
108     }
109 
110     // end of update stats...
111     population.ProcessPostUpdate(ctx);
112 
113 		m_world->ProcessPostUpdate(ctx);
114 
115     // No viewer; print out status for this update....
116     if (m_world->GetVerbosity() > VERBOSE_SILENT) {
117       cout.setf(ios::left);
118       cout.setf(ios::showpoint);
119       cout << "UD: " << setw(6) << stats.GetUpdate() << "  ";
120       cout << "Gen: " << setw(9) << setprecision(7) << stats.SumGeneration().Average() << "  ";
121       cout << "Fit: " << setw(9) << setprecision(7) << stats.GetAveFitness() << "  ";
122       cout << "Orgs: " << setw(6) << population.GetNumOrganisms() << "  ";
123       if (m_world->GetPopulation().GetNumDemes() > 1) cout << "Demes: " << setw(4) << stats.GetNumOccupiedDemes() << " ";
124       if (m_world->GetVerbosity() == VERBOSE_ON || m_world->GetVerbosity() == VERBOSE_DETAILS) {
125         cout << "Merit: " << setw(9) << setprecision(7) << stats.GetAveMerit() << "  ";
126         cout << "Thrd: " << setw(6) << stats.GetNumThreads() << "  ";
127         cout << "Para: " << stats.GetNumParasites() << "  ";
128         cout << "GenEntr: " << stats.GetEntropy() << "  ";
129       }
130       if (m_world->GetVerbosity() >= VERBOSE_DEBUG) {
131         cout << "Spec: " << setw(6) << setprecision(4) << stats.GetAveSpeculative() << "  ";
132         cout << "SWst: " << setw(6) << setprecision(4) << (((double)stats.GetSpeculativeWaste() / (double)m_world->CalculateUpdateSize()) * 100.0) << "%  ";
133         cout << "GSz: " << setw(4) << setprecision(3) << (double)((stats.GetNumGenotypes() + stats.GetNumGenotypesHistoric()) * sizeof(cBGGenotype)) / 1048576.0 << "m";
134       }
135 
136       cout << endl;
137     }
138 
139 
140     // Do Point Mutations
141     if (point_mut_prob > 0 ) {
142       for (int i = 0; i < population.GetSize(); i++) {
143         if (population.GetCell(i).IsOccupied()) {
144           int num_mut = population.GetCell(i).GetOrganism()->GetHardware().PointMutate(ctx);
145           population.GetCell(i).GetOrganism()->IncPointMutations(num_mut);
146         }
147       }
148     }
149 
150     // Keep track of changes in generation for fast-forward purposes
151     UpdateFastForward(stats.GetGeneration(),stats.GetNumCreatures());
152 
153     // Exit conditons...
154     if((population.GetNumOrganisms()==0) && m_world->AllowsEarlyExit()) {
155 			m_done = true;
156 		}
157   }
158 }
159 
RaiseException(const cString & in_string)160 void cDefaultRunDriver::RaiseException(const cString& in_string)
161 {
162   cerr << "Error: " << in_string << endl;
163 }
164 
RaiseFatalException(int exit_code,const cString & in_string)165 void cDefaultRunDriver::RaiseFatalException(int exit_code, const cString& in_string)
166 {
167   cerr << "Error: " << in_string << "  Exiting..." << endl;
168   exit(exit_code);
169 }
170 
NotifyComment(const cString & in_string)171 void cDefaultRunDriver::NotifyComment(const cString& in_string)
172 {
173   cout << in_string << endl;
174 }
175 
NotifyWarning(const cString & in_string)176 void cDefaultRunDriver::NotifyWarning(const cString& in_string)
177 {
178   cout << "Warning: " << in_string << endl;
179 }
180 
UpdateFastForward(double inGeneration,int population)181 void cDefaultRunDriver::UpdateFastForward (double inGeneration, int population)
182 {
183   if (bool(m_population_fastforward_threshold))
184   {
185     if (population >= m_population_fastforward_threshold) m_fastforward = true;
186     else m_fastforward = false;
187   }
188   if (!m_generation_update_fastforward_threshold) return;
189 
190   if (inGeneration == m_last_generation)
191   {
192     m_generation_same_update_count++;
193     if (m_generation_same_update_count >= m_generation_update_fastforward_threshold) m_fastforward = true;
194   }
195   else
196   {
197     m_generation_same_update_count = 0;
198     m_last_generation = inGeneration;
199   }
200 }
201