[Avida-SVN] r2520 - in development/source: . actions cpu main

barrick at myxo.css.msu.edu barrick at myxo.css.msu.edu
Sun Apr 6 18:49:58 PDT 2008


Author: barrick
Date: 2008-04-06 21:49:58 -0400 (Sun, 06 Apr 2008)
New Revision: 2520

Modified:
   development/source/actions/PrintActions.cc
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cHardwareCPU.h
   development/source/defs.h
   development/source/main/cAvidaConfig.h
   development/source/main/cDeme.cc
   development/source/main/cDeme.h
   development/source/main/cEnvironment.cc
   development/source/main/cOrganism.cc
   development/source/main/cOrganism.h
   development/source/main/cPhenotype.cc
   development/source/main/cPhenotype.h
   development/source/main/cPopulation.cc
   development/source/main/cPopulation.h
   development/source/main/cReactionProcess.h
   development/source/main/cReactionResult.cc
   development/source/main/cReactionResult.h
   development/source/main/cStats.cc
   development/source/main/cStats.h
Log:
* Demes can elect certain orgs to function as germlines by completing "germline=1" reactions. Various methods for how this is handled. Still in flux.
* New statistics to track how many generations pass between deme founders. More variations on deme task stat files.
* Epigenetic inheritance modes - current register and stack information can be passed to child and/or mother. (Purpose: allow differentiation within deme seeded by single organism). Only implemented in cHardwareCPU.



Modified: development/source/actions/PrintActions.cc
===================================================================
--- development/source/actions/PrintActions.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/actions/PrintActions.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -99,6 +99,9 @@
 STATS_OUT_FILE(PrintDemeTasks,              deme_tasks.dat      );
 STATS_OUT_FILE(PrintDemeTasksExe,           deme_tasks_exe.dat  );
 STATS_OUT_FILE(PrintDemeReactions,          deme_reactions.dat  );
+STATS_OUT_FILE(PrintDemeOrgTasks,           deme_org_tasks.dat      );
+STATS_OUT_FILE(PrintDemeOrgTasksExe,        deme_org_tasks_exe.dat  );
+STATS_OUT_FILE(PrintDemeOrgReactions,       deme_org_reactions.dat  );
 STATS_OUT_FILE(PrintGermlineData,           germline.dat        );
 // @WRE: Added output event for collected visit counts
 STATS_OUT_FILE(PrintCellVisitsData,         visits.dat			);
@@ -2687,6 +2690,9 @@
   action_lib->Register<cActionPrintDemeTasks>("PrintDemeTasksData");
   action_lib->Register<cActionPrintDemeTasksExe>("PrintDemeTasksExeData");
   action_lib->Register<cActionPrintDemeReactions>("PrintDemeReactionData");
+  action_lib->Register<cActionPrintDemeOrgTasks>("PrintDemeOrgTasksData");
+  action_lib->Register<cActionPrintDemeOrgTasksExe>("PrintDemeOrgTasksExeData");
+  action_lib->Register<cActionPrintDemeOrgReactions>("PrintDemeOrgReactionData");
 
   //Coalescence Clade Actions
   action_lib->Register<cActionPrintCCladeCounts>("PrintCCladeCounts");

Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/cpu/cHardwareCPU.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -425,6 +425,7 @@
   /**/
   
   m_spec_die = false;
+  m_epigenetic_state = false;
   
   m_thread_slicing_parallel = (m_world->GetConfig().THREAD_SLICING_METHOD.Get() == 1);
   m_no_cpu_cycle_time = m_world->GetConfig().NO_CPU_CYCLE_TIME.Get();
@@ -448,6 +449,7 @@
 , m_mal_active(hardware_cpu.m_mal_active)
 , m_advance_ip(hardware_cpu.m_advance_ip)
 , m_executedmatchstrings(hardware_cpu.m_executedmatchstrings)
+, m_epigenetic_state(hardware_cpu.m_epigenetic_state)
 {
 #if INSTRUCTION_COSTS
   m_inst_cost = hardware_cpu.m_inst_cost;
@@ -474,6 +476,14 @@
   m_thread_id_chart = 1; // Mark only the first thread as taken...
   m_cur_thread = 0;
   
+  // But then reset thread to have any epigenetic information we have saved
+  if (m_epigenetic_state) {
+    for (int i=0; i<NUM_REGISTERS; i++) {
+      m_threads[0].reg[i] = m_epigenetic_saved_reg[i];
+    }
+    m_threads[0].stack = m_epigenetic_saved_stack;
+  }
+  
   m_mal_active = false;
   m_executedmatchstrings = false;
   
@@ -1353,6 +1363,12 @@
 
   // Do more work if the parent lives through the birth of the offspring
   if (parent_alive) {
+  
+    if ( (m_world->GetConfig().EPIGENETIC_METHOD.Get() == EPIGENETIC_METHOD_PARENT) 
+    || (m_world->GetConfig().EPIGENETIC_METHOD.Get() == EPIGENETIC_METHOD_BOTH) ) {
+      InheritState(*this);  
+    }
+
     if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) Reset();
   }
   
@@ -1631,14 +1647,20 @@
   return true;
 }
 
-void cHardwareCPU::Divide_InheritState(cHardwareBase& in_hardware)
+// Sets the current state of the hardware and also saves this state so
+//  that future Reset() calls will reset to that epigenetic state
+void cHardwareCPU::InheritState(cHardwareBase& in_hardware)
 { 
+  m_epigenetic_state = true;
+
   cHardwareCPU& in_h = (cHardwareCPU&)in_hardware; 
   const cLocalThread& thread = in_h.GetThread(in_h.GetCurThread());
-  m_threads[m_cur_thread].stack = thread.stack;
   for (int i=0; i<NUM_REGISTERS; i++) {
-    m_threads[m_cur_thread].reg[i] = thread.reg[i];
+    m_epigenetic_saved_reg[i] = thread.reg[i];
+    m_threads[m_cur_thread].reg[i] = m_epigenetic_saved_reg[i];
   }
+  m_epigenetic_saved_stack = thread.stack;
+  m_threads[m_cur_thread].stack = m_epigenetic_saved_stack;
 }
 
 

Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/cpu/cHardwareCPU.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -169,6 +169,12 @@
   tArray<cPromoter> m_promoters;
   // Promoter Model -->
 
+  // <-- Epigenetic State
+  bool m_epigenetic_state;
+  int m_epigenetic_saved_reg[NUM_REGISTERS];
+  cCPUStack m_epigenetic_saved_stack;
+  // Epigenetic State -->
+
   bool SingleProcess_ExecuteInst(cAvidaContext& ctx, const cInstruction& cur_inst);
   
   // --------  Stack Manipulation...  --------
@@ -221,7 +227,7 @@
   bool Divide_Main2RS(cAvidaContext& ctx, const int divide_point, const int extra_lines=0, double mut_multiplier=1); //AWC 07/28/06
 
   void Divide_DoTransposons(cAvidaContext& ctx);
-  void Divide_InheritState(cHardwareBase& in_hardware);
+  void InheritState(cHardwareBase& in_hardware);
   
   void InjectCode(const cGenome& injection, const int line_num);
   

Modified: development/source/defs.h
===================================================================
--- development/source/defs.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/defs.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -136,10 +136,16 @@
   DIVIDE_METHOD_OFFSPRING = 0,
   DIVIDE_METHOD_SPLIT,
   DIVIDE_METHOD_BIRTH,
-  DIVIDE_METHOD_KEEP_STATE,
-  DIVIDE_METHOD_KEEP_STATE_EPIGENETIC
 };
 
+enum eEPIGENETIC_METHOD
+{
+  EPIGENETIC_METHOD_NONE = 0,
+  EPIGENETIC_METHOD_OFFSPRING,
+  EPIGENETIC_METHOD_PARENT,
+  EPIGENETIC_METHOD_BOTH
+};
+
 enum eINJECT_METHOD
 {
   INJECT_METHOD_OFFSPRING = 0,

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cAvidaConfig.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -317,6 +317,8 @@
   CONFIG_ADD_VAR(DEMES_NUM_X, int, 0, "Simulated number of demes in X dimension. Only used for migration. ");
   CONFIG_ADD_VAR(DEMES_SEED_METHOD, int, 0, "Deme seeding method.\n0=maintain old consistency\n1=new method using genotypes");
   CONFIG_ADD_VAR(DEMES_DIVIDE_METHOD, int, 0, "Deme divide method. Only works with DEMES_SEED_METHOD 1\n0=replace and target demes\n1= replace target deme, reset source deme to founders\n2=replace target deme, leave source deme unchanged");
+  CONFIG_ADD_VAR(DEMES_DEFAULT_GERMLINE_PROPENSITY, double, 0.0, "Default germline propensity of organisms in deme.\nFor use with DEMES_DIVIDE_METHOD 2.");
+  CONFIG_ADD_VAR(DEMES_FOUNDER_GERMLINE_PROPENSITY, double, -1.0, "Default germline propensity of founder organisms in deme.\nFor use with DEMES_DIVIDE_METHOD 2.\n <0 = OFF");
 
   CONFIG_ADD_GROUP(REPRODUCTION_GROUP, "Birth and Death");
   CONFIG_ADD_VAR(BIRTH_METHOD, int, 0, "Which organism should be replaced on birth?\n0 = Random organism in neighborhood\n1 = Oldest in neighborhood\n2 = Largest Age/Merit in neighborhood\n3 = None (use only empty cells in neighborhood)\n4 = Random from population (Mass Action)\n5 = Oldest in entire population\n6 = Random within deme\n7 = Organism faced by parent\n8 = Next grid cell (id+1)\n9 = Largest energy used in entire population\n10 = Largest energy used in neighborhood");
@@ -327,6 +329,7 @@
   CONFIG_ADD_VAR(AGE_DEVIATION, int, 0, "Creates a distribution around AGE_LIMIT");
   CONFIG_ADD_VAR(ALLOC_METHOD, int, 0, "(Orignal CPU Only)\n0 = Allocated space is set to default instruction.\n1 = Set to section of dead genome (Necrophilia)\n2 = Allocated space is set to random instruction.");
   CONFIG_ADD_VAR(DIVIDE_METHOD, int, 1, "0 = Divide leaves state of mother untouched.\n1 = Divide resets state of mother\n    (after the divide, we have 2 children)\n2 = Divide resets state of current thread only\n    (does not touch possible parasite threads)\n3 = Divide resets mother stats, but not state.\n4 = 3 + child inherits mother registers and stack values.");
+  CONFIG_ADD_VAR(EPIGENETIC_METHOD, int, 0, "Inheritance of state information other than genome\n0 = none\n1 = offspring inherits registers and stacks of first thread\n1 = parent maintains registers and stacks of first thread\n\n1 = offspring and parent keep state information");
   CONFIG_ADD_VAR(INJECT_METHOD, int, 0, "0 = Leaves the parasite thread state untouched.\n1 = Resets the calling thread state on inject");
   CONFIG_ADD_VAR(GENERATION_INC_METHOD, int, 1, "0 = Only the generation of the child is\n    increased on divide.\n1 = Both the generation of the mother and child are\n    increased on divide (good with DIVIDE_METHOD 1).");
   CONFIG_ADD_VAR(RESET_INPUTS_ON_DIVIDE, int, 0, "Reset environment inputs of parent upon successful divide.");

Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cDeme.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -45,15 +45,29 @@
   
   const int num_tasks = m_world->GetEnvironment().GetNumTasks();
   const int num_reactions = m_world->GetNumReactions();  
-  cur_task_count.Resize(num_tasks);
-  cur_task_count.SetAll(0);
+  
+  cur_task_exe_count.Resize(num_tasks);
+  cur_task_exe_count.SetAll(0);
   cur_reaction_count.ResizeClear(num_reactions);
   cur_reaction_count.SetAll(0);
-  last_task_count.ResizeClear(num_tasks);
-  last_task_count.SetAll(0);
+  last_task_exe_count.ResizeClear(num_tasks);
+  last_task_exe_count.SetAll(0);
   last_reaction_count.ResizeClear(num_reactions);
   last_reaction_count.SetAll(0);
 
+  cur_org_task_count.Resize(num_tasks);
+  cur_org_task_count.SetAll(0);
+  cur_org_task_exe_count.Resize(num_tasks);
+  cur_org_task_exe_count.SetAll(0);
+  cur_org_reaction_count.ResizeClear(num_reactions);
+  cur_org_reaction_count.SetAll(0);
+  last_org_task_count.ResizeClear(num_tasks);
+  last_org_task_count.SetAll(0);
+  last_org_task_exe_count.ResizeClear(num_tasks);
+  last_org_task_exe_count.SetAll(0);
+  last_org_reaction_count.ResizeClear(num_reactions);
+  last_org_reaction_count.SetAll(0);
+
   // If width is negative, set it to the full number of cells.
   width = in_width;
   if (width < 1) width = cell_ids.GetSize();
@@ -143,7 +157,7 @@
   birth_count = 0;
   cur_normalized_time_used = 0;
   
-  cur_task_count.SetAll(0);
+  cur_task_exe_count.SetAll(0);
   cur_reaction_count.SetAll(0);
 
   if(resetResources) deme_resource_count.ReinitializeResources();
@@ -152,18 +166,44 @@
 
 void cDeme::DivideReset(cDeme& parent_deme, bool resetResources, double deme_energy)
 {
+  // inherit last value from the parent
+  generations_per_lifetime = parent_deme.GetGenerationsPerLifetime();
+
+  // update our average founder generation
+  cDoubleSum gen;  
+  for (int i=0; i< m_founder_phenotypes.GetSize(); i++) {
+    gen.Add( m_founder_phenotypes[i].GetGeneration() );
+  }
+  avg_founder_generation = gen.Average();
+
   //Save statistics according to parent before reset.
   generation = parent_deme.GetGeneration() + 1;
   gestation_time = parent_deme.GetTimeUsed();
   last_normalized_time_used = parent_deme.GetNormalizedTimeUsed();
   
-  last_task_count = cur_task_count;
+  last_task_exe_count = cur_task_exe_count;
   last_reaction_count = cur_reaction_count;
 
+  last_org_task_count = cur_org_task_count;
+  last_org_task_exe_count = cur_org_task_exe_count;
+  last_org_reaction_count = cur_org_reaction_count;
+
   Reset(resetResources, deme_energy);
 }
 
 
+// Given the input deme founders and original ones,
+// calculate how many generations this deme went through to divide.
+void cDeme::UpdateGenerationsPerLifetime(tArray<cPhenotype>& new_founder_phenotypes) 
+{ 
+  cDoubleSum gen;
+  for (int i=0; i< new_founder_phenotypes.GetSize(); i++) {
+    gen.Add( new_founder_phenotypes[i].GetGeneration() );
+  }
+  double new_avg_founder_generation = gen.Average();
+  generations_per_lifetime = new_avg_founder_generation - avg_founder_generation;
+}
+
 /*! Check every cell in this deme for a living organism.  If found, kill it. */
 void cDeme::KillAll()
 {
@@ -175,7 +215,46 @@
   }
 }
 
+void cDeme::UpdateStats()
+{
+  //save stats about what tasks our orgs were doing
+  //usually called before KillAll
+  
+  for(int j = 0; j < cur_org_task_count.GetSize(); j++) {
+    int count = 0;
+    for(int k=0; k<GetSize(); k++) {
+      int cellid = GetCellID(k);
+      if(m_world->GetPopulation().GetCell(cellid).IsOccupied()) {
+        count += (m_world->GetPopulation().GetCell(cellid).GetOrganism()->GetPhenotype().GetLastTaskCount()[j] > 0);
+      }
+     cur_org_task_count[j] = count; 
+    }
+  }
+  
+  for(int j = 0; j < cur_org_task_exe_count.GetSize(); j++) {
+    int count = 0;
+    for(int k=0; k<GetSize(); k++) {
+      int cellid = GetCellID(k);
+      if(m_world->GetPopulation().GetCell(cellid).IsOccupied()) {
+        count += m_world->GetPopulation().GetCell(cellid).GetOrganism()->GetPhenotype().GetLastTaskCount()[j];
+      }
+     cur_org_task_exe_count[j] = count; 
+    }
+  }
 
+ for(int j = 0; j < cur_org_reaction_count.GetSize(); j++) {
+    int count = 0;
+    for(int k=0; k<GetSize(); k++) {
+      int cellid = GetCellID(k);
+      if(m_world->GetPopulation().GetCell(cellid).IsOccupied()) {
+        count += m_world->GetPopulation().GetCell(cellid).GetOrganism()->GetPhenotype().GetLastReactionCount()[j];
+      }
+     cur_org_reaction_count[j] = count; 
+    }
+  }
+}
+
+
 /*! Replacing this deme's germline has the effect of changing the deme's lineage.
 There's still some work to do here; the lineage labels of the Genomes in the germline
 are all messed up.
@@ -289,12 +368,17 @@
 
 // --- Founder list management --- //
 
-void cDeme::AddFounder(cGenotype& _in_genotype) {
+void cDeme::AddFounder(cGenotype& _in_genotype, cPhenotype * _in_phenotype) {
+
   // save genotype id
   m_founder_genotype_ids.Push( _in_genotype.GetID() );
+  cPhenotype phenotype;
+  if (_in_phenotype) phenotype = *_in_phenotype;
+  m_founder_phenotypes.Push( phenotype );
 
   // defer adjusting this genotype until we are done with it
   _in_genotype.IncDeferAdjust();
+  
 }
 
 void cDeme::ClearFounders() {
@@ -308,6 +392,7 @@
   
   // empty our list
   m_founder_genotype_ids.ResizeClear(0);
+  m_founder_phenotypes.ResizeClear(0);
 }
 
 void cDeme::ReplaceGermline(cGenotype& _in_genotype) {

Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cDeme.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -26,6 +26,7 @@
 
 #include "cDemeCellEvent.h"
 #include "cGermline.h"
+#include "cPhenotype.h"
 #include "cMerit.h"
 #include "tArray.h"
 #include "cResourceCount.h"
@@ -35,6 +36,7 @@
 class cWorld;
 class cPopulationCell;
 class cGenotype;
+class cOrganism;
 
 /*! Demes are groups of cells in the population that are somehow bound together
 as a unit.  The deme object is used from within cPopulation to manage these 
@@ -59,11 +61,21 @@
   double cur_normalized_time_used; // normalized by merit and number of orgs
   double last_normalized_time_used; 
   
-  tArray<int> cur_task_count;
+  tArray<int> cur_task_exe_count;
   tArray<int> cur_reaction_count;
-  tArray<int> last_task_count;
+  tArray<int> last_task_exe_count;
   tArray<int> last_reaction_count;
   
+  tArray<int> cur_org_task_count;
+  tArray<int> cur_org_task_exe_count;
+  tArray<int> cur_org_reaction_count;
+  tArray<int> last_org_task_count;
+  tArray<int> last_org_task_exe_count;
+  tArray<int> last_org_reaction_count;
+  
+  double avg_founder_generation;  //Average generation of current founders                                    
+  double generations_per_lifetime; //Generations between current founders and founders of parent  
+
   // End of phenotypic traits
   
   cGermline _germline; //!< The germline for this deme, if used.
@@ -78,6 +90,7 @@
   int         m_germline_genotype_id; // Genotype id of germline (if in use)
   tArray<int> m_founder_genotype_ids; // List of genotype ids used to found deme.
                                       // Keep a lease on these genotypes for the deme's lifetime.
+  tArray<cPhenotype> m_founder_phenotypes; // List of phenotypes of founder organsisms                                    
                                       
   cMerit _current_merit; //!< Deme merit applied to all organisms living in this deme.
   cMerit _next_merit; //!< Deme merit that will be inherited upon deme replication.
@@ -85,6 +98,7 @@
 public:
   cDeme() : _id(0), width(0), birth_count(0), org_count(0), _age(0), generation(0), total_org_energy(0.0),
             time_used(0), gestation_time(0), cur_normalized_time_used(0.0), last_normalized_time_used(0.0), 
+            avg_founder_generation(0.0), generations_per_lifetime(0.0),
             deme_resource_count(0), m_germline_genotype_id(0) { ; }
   ~cDeme() { ; }
 
@@ -106,6 +120,8 @@
 
   //! Kills all organisms currently in this deme.
   void KillAll();
+  void UpdateStats();
+  
   int GetBirthCount() const { return birth_count; }
   void IncBirthCount() { birth_count++; }
 
@@ -136,12 +152,16 @@
   const cMerit& GetHeritableDemeMerit() const { return _next_merit; }
 
 
-  void AddCurTask(int task_num) { cur_task_count[task_num]++; }
+  void AddCurTask(int task_num) { cur_task_exe_count[task_num]++; }
   void AddCurReaction (int reaction_num) { cur_reaction_count[reaction_num]++; }
 
-  const tArray<int>& GetLastTaskCount() const { return last_task_count; }
+  const tArray<int>& GetLastTaskExeCount() const { return last_task_exe_count; }
   const tArray<int>& GetLastReactionCount() const { return last_reaction_count; }
 
+  const tArray<int>& GetLastOrgTaskCount() const { return last_org_task_count; }
+  const tArray<int>& GetLastOrgTaskExeCount() const { return last_org_task_exe_count; }
+  const tArray<int>& GetLastOrgReactionCount() const { return last_org_reaction_count; }
+
   bool HasDemeMerit() const { return _current_merit.GetDouble() != 1.0; }
 
   // -= Update support =-
@@ -175,9 +195,13 @@
 
   // --- Founder list management --- //
   void ClearFounders();
-  void AddFounder(cGenotype& _in_genotype);
-  tArray<int>& GetFounders() { return m_founder_genotype_ids; }
-  
+  void AddFounder(cGenotype& _in_genotype, cPhenotype * _in_phenotype = NULL);
+  tArray<int>& GetFounderGenotypeIDs() { return m_founder_genotype_ids; }
+  tArray<cPhenotype>& GetFounderPhenotypes() { return m_founder_phenotypes; }
+  double GetAvgFounderGeneration() { return avg_founder_generation; }        
+  void UpdateGenerationsPerLifetime(tArray<cPhenotype>& new_founder_phenotypes);   
+  double GetGenerationsPerLifetime() { return generations_per_lifetime; }  
+
   // --- Germline management --- //
   void ReplaceGermline(cGenotype& _in_genotype);
   int GetGermlineGenotypeID() { return m_germline_genotype_id; }

Modified: development/source/main/cEnvironment.cc
===================================================================
--- development/source/main/cEnvironment.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cEnvironment.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -212,6 +212,11 @@
         return false;
       new_process->SetDemeFraction(var_value.AsDouble());
     }
+    else if (var_name == "germline") {
+      if (!AssertInputBool(var_value, "germline", var_type))
+        return false;
+      new_process->SetIsGermline(var_value.AsInt());
+    }
     else if (var_name == "detect") {
       cResource* test_resource = resource_lib.GetResource(var_value);
       if (!AssertInputValid(test_resource, "product", var_type, var_value)) {
@@ -1027,57 +1032,87 @@
     // Mark the reaction as having been performed if we get here.
     result.MarkReaction(reaction_id);
     
-    // How much of this bonus belongs to the deme, and how much belongs to the organism?
-    double deme_bonus = cur_process->GetDemeFraction() * consumed * cur_process->GetValue();
-    double bonus = (1.0 - cur_process->GetDemeFraction()) * consumed * cur_process->GetValue();
-
-    // Take care of the organism's bonus:
-    switch (cur_process->GetType()) {
-      case nReaction::PROCTYPE_ADD:
-        result.AddBonus(bonus, reaction_id);
-        result.AddDemeBonus(deme_bonus);
-        break;
-      case nReaction::PROCTYPE_MULT:
-        result.MultBonus(bonus);
-        result.MultDemeBonus(deme_bonus);
-        break;
-      case nReaction::PROCTYPE_POW:
-        result.MultBonus(pow(2.0, bonus));
-        result.MultDemeBonus(pow(2.0, deme_bonus));
-        break;
-      case nReaction::PROCTYPE_LIN:
-        result.AddBonus(bonus * task_count, reaction_id);
-        assert(deme_bonus == 0.0);
-        break;
-      case nReaction::PROCTYPE_ENERGY:
-        result.AddEnergy(bonus);
-        assert(deme_bonus == 0.0);
-        break;
-      case nReaction::PROCTYPE_ENZYME: //@JEB
-      {
-        const int res_id = in_resource->GetID();
-        assert(cur_process->GetMaxFraction() != 0);
-        assert(resource_count[res_id] != 0);
-        double reward = cur_process->GetValue() * resource_count[res_id] / (resource_count[res_id] + cur_process->GetMaxFraction());
-        result.AddBonus( reward , reaction_id);
-        break;
+    double bonus = consumed * cur_process->GetValue();
+    
+    if (!cur_process->GetIsGermline())
+    {
+      // normal bonus
+      double deme_bonus = 0;
+       
+      // How much of this bonus belongs to the deme, and how much belongs to the organism?
+      if (cur_process->GetDemeFraction()) {
+        deme_bonus = cur_process->GetDemeFraction() * bonus;
+        bonus = (1-cur_process->GetDemeFraction()) * bonus;
       }
-      case nReaction::PROCTYPE_EXP: //@JEB
-      {
-        // Cumulative rewards are Value * integral (exp (-MaxFraction * TaskCount))
-        // Evaluate to get stepwise amount to add per task executed.
-        assert(task_count >= 1);
-        const double decay = cur_process->GetMaxFraction();
-        const double value = cur_process->GetValue();
-        result.AddBonus( value * (1.0 / decay) * ( exp((task_count-1) * decay) - exp(task_count * decay)), reaction_id );
-        break;
+      
+      // Take care of the organism's bonus:
+      switch (cur_process->GetType()) {
+        case nReaction::PROCTYPE_ADD:
+          result.AddBonus(bonus, reaction_id);
+          result.AddDemeBonus(deme_bonus);
+          break;
+        case nReaction::PROCTYPE_MULT:
+          result.MultBonus(bonus);
+          // @JEB: since deme_bonus is ZERO by default this will cause
+          // a problem if we unintentionally multiply the deme's bonus
+          // when we do not make a deme reaction, i.e. deme=0!
+          // Other cases ADD zero, so they don't necessarily need this check.
+          if (cur_process->GetDemeFraction()) result.MultDemeBonus(deme_bonus);
+          break;
+        case nReaction::PROCTYPE_POW:
+          result.MultBonus(pow(2.0, bonus));
+          result.MultDemeBonus(pow(2.0, deme_bonus));
+          break;
+        case nReaction::PROCTYPE_LIN:
+          result.AddBonus(bonus * task_count, reaction_id);
+          break;
+        case nReaction::PROCTYPE_ENERGY:
+          result.AddEnergy(bonus);
+          assert(deme_bonus == 0.0);
+          break;
+        case nReaction::PROCTYPE_ENZYME: //@JEB -- experimental
+        {
+          const int res_id = in_resource->GetID();
+          assert(cur_process->GetMaxFraction() != 0);
+          assert(resource_count[res_id] != 0);
+          double reward = cur_process->GetValue() * resource_count[res_id] / (resource_count[res_id] + cur_process->GetMaxFraction());
+          result.AddBonus( reward , reaction_id);
+          break;
+        }
+        case nReaction::PROCTYPE_EXP: //@JEB -- experimental
+        {
+          // Cumulative rewards are Value * integral (exp (-MaxFraction * TaskCount))
+          // Evaluate to get stepwise amount to add per task executed.
+          assert(task_count >= 1);
+          const double decay = cur_process->GetMaxFraction();
+          const double value = cur_process->GetValue();
+          result.AddBonus( value * (1.0 / decay) * ( exp((task_count-1) * decay) - exp(task_count * decay)), reaction_id );
+          break;
+        }   
+             
+        default:
+          assert(false);  // Should not get here!
+          break;
       }
-          
-      default:
-        assert(false);  // Should not get here!
-        break;
-    };
-
+    } else {  // if (cur_process->GetIsGermline())
+     // @JEB -- this process changes germline propensities, not bonus
+      switch (cur_process->GetType()) {
+        case nReaction::PROCTYPE_ADD:
+          result.AddGermline(bonus);
+          break;
+        case nReaction::PROCTYPE_MULT:
+          result.MultGermline(bonus);
+          break;
+        case nReaction::PROCTYPE_POW:
+          result.MultGermline(pow(2.0, bonus));
+          break;
+                  
+        default:
+          assert(false);  // Should not get here!
+          break;
+      }
+    }
+    
     // Determine detection events
     cResource* detected = cur_process->GetDetect();
     if (detected != NULL) {

Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cOrganism.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -266,8 +266,6 @@
   //update deme resources
   m_interface->UpdateDemeResources(deme_res_change);  
 
-  //if(m_world->GetConfig().CLEAR_ON_OUTPUT.Get()) input_buffer.Clear();  @JEB Not fully implemented 
-
   for (int i = 0; i < insts_triggered.GetSize(); i++) {
     const int cur_inst = insts_triggered[i];
     m_hardware->ProcessBonusInst(ctx, cInstruction(cur_inst));

Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cOrganism.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -150,6 +150,7 @@
   cGenotype* GetGenotype() const { return m_genotype; }
   const cPhenotype& GetPhenotype() const { return m_phenotype; }
   cPhenotype& GetPhenotype() { return m_phenotype; }
+  void SetPhenotype(cPhenotype& _in_phenotype) { m_phenotype = _in_phenotype; }
 
   const cGenome& GetGenome() const { return m_initial_genome; }
   

Modified: development/source/main/cPhenotype.cc
===================================================================
--- development/source/main/cPhenotype.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cPhenotype.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -115,7 +115,8 @@
   cur_sense_count          = in_phen.cur_sense_count;                 
   sensed_resources         = in_phen.sensed_resources;            
   cur_task_time            = in_phen.cur_task_time;   
-  
+  cur_child_germline_propensity = in_phen.cur_child_germline_propensity;
+
   // Dynamically allocated m_task_states requires special handling
   tList<cTaskState*> hash_values;
   tList<void*>       hash_keys;
@@ -142,7 +143,8 @@
   last_inst_count          = in_phen.last_inst_count;	  
   last_sense_count         = in_phen.last_sense_count;   
   last_fitness             = in_phen.last_fitness;            
-  
+  last_child_germline_propensity = in_phen.last_child_germline_propensity;
+
   // 4. Records from this organisms life...
   num_divides              = in_phen.num_divides;      
   generation               = in_phen.generation;        
@@ -211,6 +213,9 @@
   child_fertile           = in_phen.child_fertile;  
   last_child_fertile      = in_phen.last_child_fertile; 
   child_copied_size       = in_phen.child_copied_size;
+
+  // 7. Permanent information...
+  permanent_germline_propensity = in_phen.permanent_germline_propensity;
          
   return *this;
 }
@@ -295,7 +300,8 @@
   cur_trial_times_used.Resize(0); 
   trial_time_used = 0;
   trial_cpu_cycles_used = 0;
-  
+  cur_child_germline_propensity = m_world->GetConfig().DEMES_DEFAULT_GERMLINE_PROPENSITY.Get();
+
   // Copy last values from parent
   last_merit_base           = parent_phenotype.last_merit_base;
   last_bonus                = parent_phenotype.last_bonus;
@@ -304,12 +310,13 @@
   last_num_donates          = parent_phenotype.last_num_donates;
   last_task_count           = parent_phenotype.last_task_count;
   last_task_quality         = parent_phenotype.last_task_quality;
-  last_task_value			= parent_phenotype.last_task_value;
+  last_task_value           = parent_phenotype.last_task_value;
   last_reaction_count       = parent_phenotype.last_reaction_count;
   last_reaction_add_reward  = parent_phenotype.last_reaction_add_reward;
   last_inst_count           = parent_phenotype.last_inst_count;
   last_sense_count          = parent_phenotype.last_sense_count;
   last_fitness              = CalcFitness(last_merit_base, last_bonus, gestation_time, last_cpu_cycles_used);
+  last_child_germline_propensity = parent_phenotype.last_child_germline_propensity;   // chance of child being a germline cell; @JEB
 
   // Setup other miscellaneous values...
   num_divides     = 0;
@@ -381,6 +388,9 @@
   child_fertile      = true;
   child_copied_size  = 0;
 
+  // permanently set germline propensity of org (since DivideReset is called first, it is now in the "last" slot...)
+  permanent_germline_propensity  = parent_phenotype.last_child_germline_propensity;
+
   initialized = true;
 }
 
@@ -429,7 +439,8 @@
   cur_trial_times_used.Resize(0); 
   trial_time_used = 0;
   trial_cpu_cycles_used = 0;
-  
+  cur_child_germline_propensity = m_world->GetConfig().DEMES_DEFAULT_GERMLINE_PROPENSITY.Get();
+
   // Copy last values from parent
   last_merit_base = genome_length;
   last_bonus      = 1;
@@ -443,6 +454,7 @@
   last_reaction_add_reward.SetAll(0);
   last_inst_count.SetAll(0);
   last_sense_count.SetAll(0);
+  last_child_germline_propensity = m_world->GetConfig().DEMES_DEFAULT_GERMLINE_PROPENSITY.Get();
 
   // Setup other miscellaneous values...
   num_divides     = 0;
@@ -513,6 +525,8 @@
   last_child_fertile = true;
   child_copied_size = 0;
 
+  permanent_germline_propensity = m_world->GetConfig().DEMES_DEFAULT_GERMLINE_PROPENSITY.Get();
+
   initialized = true;
 }
 
@@ -561,6 +575,7 @@
   last_reaction_add_reward  = cur_reaction_add_reward;
   last_inst_count           = cur_inst_count;
   last_sense_count          = cur_sense_count;
+  last_child_germline_propensity = cur_child_germline_propensity;
 
   // Reset cur values.
   cur_bonus       = m_world->GetConfig().DEFAULT_BONUS.Get();
@@ -577,6 +592,7 @@
   cur_inst_count.SetAll(0);
   cur_sense_count.SetAll(0);
   cur_task_time.SetAll(0.0);
+  cur_child_germline_propensity = m_world->GetConfig().DEMES_DEFAULT_GERMLINE_PROPENSITY.Get();
 
   // Setup other miscellaneous values...
   num_divides++;
@@ -646,9 +662,7 @@
 
   // A few final changes if the parent was supposed to be be considered
   // a second child on the divide.
-  if ( (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT)
-    || (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE)
-    || (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE_EPIGENETIC) ) {
+  if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
     gestation_start = 0;
     cpu_cycles_used = 0;
     time_used = 0;
@@ -704,7 +718,8 @@
   last_reaction_add_reward  = cur_reaction_add_reward;
   last_inst_count           = cur_inst_count;
   last_sense_count          = cur_sense_count;  
-
+  last_child_germline_propensity = cur_child_germline_propensity;
+  
   // Reset cur values.
   cur_bonus       = m_world->GetConfig().DEFAULT_BONUS.Get();
   cpu_cycles_used = 0;
@@ -725,6 +740,7 @@
   cur_trial_times_used.Resize(0); 
   trial_time_used = 0;
   trial_cpu_cycles_used = 0;
+  cur_child_germline_propensity = m_world->GetConfig().DEMES_DEFAULT_GERMLINE_PROPENSITY.Get();
 
   // Setup other miscellaneous values...
   num_divides++;
@@ -846,6 +862,7 @@
   cur_trial_times_used.Resize(0); 
   trial_time_used = 0;
   trial_cpu_cycles_used = 0;
+  cur_child_germline_propensity = m_world->GetConfig().DEMES_DEFAULT_GERMLINE_PROPENSITY.Get();
 
   // Copy last values from parent
   last_merit_base          = clone_phenotype.last_merit_base;
@@ -859,6 +876,7 @@
   last_inst_count          = clone_phenotype.last_inst_count;
   last_sense_count         = clone_phenotype.last_sense_count;  
   last_fitness             = CalcFitness(last_merit_base, last_bonus, gestation_time, last_cpu_cycles_used);
+  last_child_germline_propensity = clone_phenotype.last_child_germline_propensity;
 
   // Setup other miscellaneous values...
   num_divides     = 0;
@@ -930,6 +948,7 @@
   last_child_fertile = is_fertile;
   child_fertile      = true;
   child_copied_size  = 0;
+  permanent_germline_propensity = clone_phenotype.permanent_germline_propensity;
 
   initialized = true;
 }
@@ -1003,14 +1022,21 @@
   cur_bonus *= result.GetMultBonus();
   cur_bonus += result.GetAddBonus();
   
+  // update the germline propensity
+  cur_child_germline_propensity += result.GetAddGermline();
+  cur_child_germline_propensity *= result.GetMultGermline();
+  
   // Update deme merit (guard against running in the test CPU, where there is
   // no deme object.  Don't touch deme merit if there is no deme frac component.
   cDeme* deme = taskctx.GetOrganism()->GetOrgInterface().GetDeme();
-  if(deme && result.GetActiveDeme()) {
-    double deme_bonus = deme->GetHeritableDemeMerit().GetDouble();
-    deme_bonus *= result.GetMultDemeBonus();
-    deme_bonus += result.GetAddDemeBonus();
-    deme->UpdateHeritableDemeMerit(deme_bonus);
+  if(deme) {
+  
+    if (result.GetActiveDeme()) {
+      double deme_bonus = deme->GetHeritableDemeMerit().GetDouble();
+      deme_bonus *= result.GetMultDemeBonus();
+      deme_bonus += result.GetAddDemeBonus();
+      deme->UpdateHeritableDemeMerit(deme_bonus);
+    }
     
     //also count tasks/reactions
     for (int i = 0; i < num_tasks; i++) {
@@ -1514,7 +1540,7 @@
   cur_reaction_add_reward.SetAll(0);
   cur_inst_count.SetAll(0);
   cur_sense_count.SetAll(0);
-  //cur_trial_fitnesses.Resize(0); Don't throw out the tiral fitnesses! @JEB
+  //cur_trial_fitnesses.Resize(0); Don't throw out the trial fitnesses! @JEB
   trial_time_used = 0;
   trial_cpu_cycles_used = 0;
 
@@ -1574,7 +1600,6 @@
   (void) parent_true;
   (void) parent_sex;
   (void) parent_cross_num;
-
 }
 
 /**
@@ -1614,9 +1639,7 @@
 
   // A few final changes if the parent was supposed to be be considered
   // a second child on the divide.
-  if ( (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT)
-    || (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE)
-    || (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE_EPIGENETIC) ) {    
+  if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {    
     gestation_start = 0;
     cpu_cycles_used = 0;
     time_used = 0;

Modified: development/source/main/cPhenotype.h
===================================================================
--- development/source/main/cPhenotype.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cPhenotype.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -123,10 +123,11 @@
   tHashTable<void*, cTaskState*> m_task_states;
   tArray<double> cur_trial_fitnesses;         // Fitnesses of various trials.; @JEB
   tArray<double> cur_trial_bonuses;           // Bonuses of various trials.; @JEB
-  tArray<int> cur_trial_times_used;        // Time used in of various trials.; @JEB
+  tArray<int> cur_trial_times_used;           // Time used in of various trials.; @JEB
   int trial_time_used;                        // like time_used, but reset every trial; @JEB
   int trial_cpu_cycles_used;                  // like cpu_cycles_used, but reset every trial; @JEB
-  
+  double last_child_germline_propensity;   // chance of child being a germline cell; @JEB
+
   // 3. These mark the status of "in progess" variables at the last divide.
   double last_merit_base;         // Either constant or based on genome length.
   double last_bonus;
@@ -142,6 +143,7 @@
   tArray<int> last_sense_count;   // Total times resource combinations have been sensed; @JEB 
   double last_fitness;            // Used to determine sterilization.
   int last_cpu_cycles_used;
+  double cur_child_germline_propensity;   // chance of child being a germline cell; @JEB
 
   // 4. Records from this organisms life...
   int num_divides;       // Total successful divides organism has produced.
@@ -212,15 +214,14 @@
   bool last_child_fertile;  // Was the child being born to be fertile?
   int child_copied_size; // Instruction copied into child.
 
-
-  cPhenotype(); // @not_implemented
+  // 7. Information that is set once (when organism was born)
+  double permanent_germline_propensity;
   
-protected:
+public:
+  cPhenotype() { ; } // @not_implemented
+  cPhenotype(cWorld* world);
   cPhenotype(const cPhenotype&); 
   cPhenotype& operator=(const cPhenotype&); 
-  
-public:
-  cPhenotype(cWorld* world);
   ~cPhenotype();
 
   bool OK();
@@ -320,6 +321,7 @@
   const tArray<int>& GetLastInstCount() const { assert(initialized == true); return last_inst_count; }
   const tArray<int>& GetLastSenseCount() const { assert(initialized == true); return last_sense_count; }
   double GetLastFitness() const { assert(initialized == true); return last_fitness; }
+  double GetPermanentGermlinePropensity() const { assert(initialized == true); return permanent_germline_propensity; }
 
   int GetNumDivides() const { assert(initialized == true); return num_divides;}
   int GetGeneration() const { assert(initialized == true); return generation; }
@@ -392,6 +394,8 @@
   void SetGestationTime(int in_time) { gestation_time = in_time; }
   void SetTimeUsed(int in_time) { time_used = in_time; }
   void SetTrialTimeUsed(int in_time) { trial_time_used = in_time; }
+  void SetGeneration(int in_generation) { generation = in_generation; }
+  void SetPermanentGermlinePropensity(double _in) { permanent_germline_propensity = _in; }
   void SetFault(const cString& in_fault) { fault_desc = in_fault; }
   void SetNeutralMetric(double _in){ neutral_metric = _in; }
   void SetLifeFitness(double _in){ life_fitness = _in; }
@@ -438,6 +442,7 @@
   void IncErrors()   { assert(initialized == true); cur_num_errors++; }
   void IncDonates()   { assert(initialized == true); cur_num_donates++; }
   void IncSenseCount(const int i) { assert(initialized == true); cur_sense_count[i]++; }  
+  
   bool& IsInjected() { assert(initialized == true); return is_injected; }
   bool& IsModifier() { assert(initialized == true); return is_modifier; }
   bool& IsModified() { assert(initialized == true); return is_modified; }

Modified: development/source/main/cPopulation.cc
===================================================================
--- development/source/main/cPopulation.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cPopulation.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -398,7 +398,8 @@
     ActivateOrganism(ctx, child_array[i], GetCell(target_cells[i]));
     
     //@JEB - we may want to pass along some state information from parent to child
-    if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_KEEP_STATE_EPIGENETIC) {
+    if ( (m_world->GetConfig().EPIGENETIC_METHOD.Get() == EPIGENETIC_METHOD_OFFSPRING) 
+      || (m_world->GetConfig().EPIGENETIC_METHOD.Get() == EPIGENETIC_METHOD_BOTH) ) {
       child_array[i]->GetHardware().InheritState(parent_organism.GetHardware());
     }
     
@@ -521,6 +522,7 @@
   
   // Keep track of statistics for organism counts...
   num_organisms++;
+
   if (deme_array.GetSize() > 0) {
     deme_array[target_cell.GetDemeID()].IncOrgCount();
   }
@@ -687,6 +689,7 @@
   
   // Update count statistics...
   num_organisms--;
+  
   if (deme_array.GetSize() > 0) {
     deme_array[in_cell.GetDemeID()].DecOrgCount();
   }
@@ -1328,6 +1331,7 @@
   }
   
   // Reset both demes, in case they have any cleanup work to do.
+  // Must reset target first for stats to be correctly updated!
   if(m_world->GetConfig().ENERGY_ENABLED.Get()) {
     // Transfer energy from source to target if we're using the energy model.
     target_deme.DivideReset(source_deme, target_deme_resource_reset, offspring_deme_energy);
@@ -1438,9 +1442,12 @@
       assert(xfer.size()>0);
       
       // Clear the demes.
+      source_deme.UpdateStats();
       source_deme.KillAll();
+
+      target_deme.UpdateStats();
       target_deme.KillAll();
-      
+
       // And now populate the source and target.
       int j=0;
       for(std::vector<std::pair<cGenome,int> >::iterator i=xfer.begin(); i!=xfer.end(); ++i, ++j) {
@@ -1458,9 +1465,23 @@
       // Updated seed deme method that maintains genotype inheritance.
       
       tArray<cOrganism*> founders; // List of organisms we're going to transfer.
+ 
+      /*
+      // Debug Code
+      cGenotype * original_source_founder_genotype = NULL;
+      if (1) {
+        tArray<int>& source_founders = source_deme.GetFounderGenotypeIDs();
+        if (source_founders.GetSize() > 0) {
+          original_source_founder_genotype = m_world->GetClassificationManager().FindGenotype(source_founders[0]);
+          cout << "Source:" << endl << original_source_founder_genotype->GetGenome().AsString() << endl;
+        }
+        tArray<int>& target_founders = target_deme.GetFounderGenotypeIDs();
+        if (target_founders.GetSize() > 0) {
+          cGenotype * target_founder_genotype = m_world->GetClassificationManager().FindGenotype(target_founders[0]);
+          cout << "Target:" << endl << target_founder_genotype->GetGenome().AsString() << endl;
+        }
+      }
 
-      /*
-      // Debug
       tArray<int>& source_founders = source_deme.GetFounders();
       cerr << "Original source genotype ids:" << endl;
       for(int i=0; i<source_founders.GetSize(); i++) {
@@ -1474,6 +1495,22 @@
         cerr << target_founders[i] << " ";
       }
       cerr << endl;
+      
+      // Debug Code
+      //// Count the number of orgs in each deme.
+      int count = 0;
+      for(int i=0; i<target_deme.GetSize(); ++i) {
+        int cell_id = target_deme.GetCellID(i);
+        if(cell_array[cell_id].IsOccupied()) count++;
+      }
+      cout << "Initial orgs in target deme: " << count << endl;
+
+      count = 0;
+      for(int i=0; i<source_deme.GetSize(); ++i) {
+        int cell_id = source_deme.GetCellID(i);
+        if(cell_array[cell_id].IsOccupied()) count++;
+      }
+      cout << "Initial orgs in source deme: " << count << endl;     
       */
       
       switch(m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get()) {
@@ -1496,16 +1533,132 @@
           }
           break;
         }
+        case 2: 
+        case 3:
+        { // Selection based on germline propensities.
+          // 2: sum the germline propensities of all organisms
+          // and pick TWO based on each organism getting a 
+          // weighted probability of being germline
+          // 3: treat germline propensities as zero or nonzero for picking
+          
+          if (source_deme.GetOrgCount() < 2) {
+            m_world->GetDriver().RaiseFatalException(1, "Germline DEMES_ORGANISM_SELECTION method didn't find at least two organisms in deme.");
+          }
+          
+          if (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() != 0) {
+            m_world->GetDriver().RaiseFatalException(1, "Germline DEMES_ORGANISM_SELECTION methods 2 and 3 can only be used with DEMES_DIVIDE_METHOD 0.");
+          }
+          
+          tArray<cOrganism*> prospective_founders;
+          
+          cDoubleSum gp_sum;
+          double min = -1;
+          for (int i=0; i < source_deme.GetSize(); i++) {
+            if ( GetCell(source_deme.GetCellID(i)).IsOccupied() ) {
+              double gp = GetCell(source_deme.GetCellID(i)).GetOrganism()->GetPhenotype().GetPermanentGermlinePropensity();
+              if (gp > 0.0) {
+                gp_sum.Add( gp );
+                prospective_founders.Push( GetCell(source_deme.GetCellID(i)).GetOrganism() );
+              }
+              //cout << gp << " ";
+              if ( (min == -1) || (gp < min) ) min = gp;
+            }
+          }
+          
+          //cout << "Germline Propensity Sum: " << gp_sum.Sum() << endl;
+          //cout << "Num prospective founders: " << prospective_founders.GetSize() << endl;
+          
+          if (prospective_founders.GetSize() < 2) {
+            // there were not enough orgs with nonzero germlines
+            // pick additional orgs at random without replacement
+            
+            founders = prospective_founders;
+            
+            while(founders.GetSize() < 2) {
+              int cellid = source_deme.GetCellID(random.GetUInt(source_deme.GetSize()));
+              if( cell_array[cellid].IsOccupied() ) {
+                cOrganism * org = cell_array[cellid].GetOrganism();
+                bool found = false;
+                for(int i=0; i< founders.GetSize(); i++) {
+                  if (founders[i] == org) found = true;
+                }
+                if (!found) founders.Push(cell_array[cellid].GetOrganism());
+              }
+            }   
+          } else {
+          
+          // pick two orgs based on germline propensities from prospective founders
+
+            while(founders.GetSize() < 2) {
+            
+              double choice = (m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get() == 2)
+                ? random.GetDouble( gp_sum.Sum() ) : random.GetDouble( gp_sum.Count() );
+
+
+              //cout <<  "Count: " << gp_sum.Count() << endl;
+              
+              // find the next organism to choose
+              cOrganism * org = NULL;
+              int on = 0;
+              while( (choice > 0) && (on < prospective_founders.GetSize()) ) {
+                org = prospective_founders[on];
+                
+                // did we already have this org?
+                bool found = false;
+                for(int i=0; i< founders.GetSize(); i++) {
+                  if (founders[i] == org) found = true;
+                }
+                
+                // if it wasn't already chosen, then we count down...
+                if (!found) {
+                  choice -= (m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get() == 2) 
+                    ? org->GetPhenotype().GetPermanentGermlinePropensity()
+                    : (org->GetPhenotype().GetPermanentGermlinePropensity() > 0);
+                }
+                on++;
+              }
+              
+              gp_sum.Subtract(org->GetPhenotype().GetPermanentGermlinePropensity());
+              assert(org);
+              founders.Push(org);
+            }
+          }             
+          /*
+          // Debug Code
+          cout << endl;
+          cout << "sum " << gp_sum.Sum() << endl;
+          cout << "min " << min << endl;
+          cout << "choice " << choice << endl;
+          */
+            
+          //cout << "Chose germline propensity " << chosen_org->GetPhenotype().GetLastGermlinePropensity() << endl;
+          break;
+        }  
         default: {
           cout << "Undefined value (" << m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get()
             << ") for DEMES_ORGANISM_SELECTION." << endl;
           exit(1);
         }
       }
-          
+      
+      // deconstruct founders into two lists...
+      tArray<cOrganism*> source_founders = founders; // List of organisms we're going to transfer.
+      tArray<cOrganism*> target_founders = founders; // List of organisms we're going to transfer.
+
+      if ( (m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get() == 2)
+        || (m_world->GetConfig().DEMES_ORGANISM_SELECTION.Get() == 3) )
+      {
+        source_founders.ResizeClear(0);
+        target_founders.ResizeClear(0);
+        
+        source_founders.Push(founders[0]);
+        target_founders.Push(founders[1]);
+      }
+      
       // We'd better have at *least* one genome.
-      assert(founders.GetSize()>0);
-      
+      assert(source_founders.GetSize()>0);
+      assert(target_founders.GetSize()>0);
+
       // We clear the deme, but trick cPopulation::KillOrganism
       // to NOT delete the organisms, by pretending 
       // the orgs are running. This way we can still create 
@@ -1513,6 +1666,7 @@
       // We also need to defer adjusting the genotype
       // or it will be prematurely deleted before we are done!
       
+     // cDoubleSum gen;
       tArray<cOrganism*> old_source_organisms;
       for(int i=0; i<source_deme.GetSize(); ++i) {
         int cell_id = source_deme.GetCellID(i);
@@ -1522,8 +1676,14 @@
           old_source_organisms.Push(org);
           org->SetRunning(true);
           org->GetGenotype()->IncDeferAdjust();
+          
+         // cout << org->GetPhenotype().GetGeneration()-source_deme.GetAvgFounderGeneration() << " ";
+         // gen.Add(org->GetPhenotype().GetGeneration()-source_deme.GetAvgFounderGeneration());
         }
       }  
+      //cout << endl;
+      //cout << "Average: " << gen.Average() << endl;
+
       
       tArray<cOrganism*> old_target_organisms;
       for(int i=0; i<target_deme.GetSize(); ++i) {
@@ -1539,17 +1699,20 @@
       
       // Clear the demes.
       target_deme.ClearFounders();
+      target_deme.UpdateStats();
       target_deme.KillAll();
-      
+
+      //cout << founders.GetSize() << " founders." << endl;
+
       // Now populate the target (and optionally the source) using InjectGenotype.
       // In the future InjectClone could be used, but this would require the 
       // deme keeping complete copies of the founder organisms when
       // we wanted to re-seed from the original founders.
-      for(int i=0; i<founders.GetSize(); i++) {
+      for(int i=0; i<target_founders.GetSize(); i++) {
           int cellid = DemeSelectInjectionCell(target_deme, i);
-          InjectGenotype(cellid, founders[i]->GetGenotype());        
-          DemePostInjection(target_deme, cell_array[cellid]);  
-          target_deme.AddFounder(*founders[i]->GetGenotype());          
+          InjectDemeFounder(cellid, *target_founders[i]->GetGenotype(), &target_founders[i]->GetPhenotype());
+          target_deme.AddFounder(*target_founders[i]->GetGenotype(), &target_founders[i]->GetPhenotype());
+          DemePostInjection(target_deme, cell_array[cellid]);
       }
       
       // We either repeat this procedure in the source deme,
@@ -1557,32 +1720,41 @@
       // or do nothing to the source deme...
       
       // source deme is replaced in the same way as the target
-      if (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 0) {
+      if (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 0) {    
+
         source_deme.ClearFounders();
+        source_deme.UpdateStats();
         source_deme.KillAll();
         
-        for(int i=0; i<founders.GetSize(); i++) {
-          int cellid = DemeSelectInjectionCell(source_deme, i);
-          InjectGenotype(cellid, founders[i]->GetGenotype());
+        for(int i=0; i<source_founders.GetSize(); i++) {
+          int cellid = DemeSelectInjectionCell(source_deme, i); 
+          InjectDemeFounder(cellid, *source_founders[i]->GetGenotype(), &source_founders[i]->GetPhenotype());
+          source_deme.AddFounder(*source_founders[i]->GetGenotype(), &source_founders[i]->GetPhenotype());
           DemePostInjection(source_deme, cell_array[cellid]);
-          source_deme.AddFounder(*founders[i]->GetGenotype());          
         }
       }
       // source deme is "reset" by re-injecting founder genotypes
       else if (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 1) {
-          
+        // Do not update the last founder generation, since the founders have not changed.
+        
+        source_deme.UpdateStats();
         source_deme.KillAll();
         // do not clear or change founder list
         
         // use it to recreate ancestral state of genotypes
-        tArray<int>& source_founders = source_deme.GetFounders();
+        tArray<int>& source_founders = source_deme.GetFounderGenotypeIDs();
+        tArray<cPhenotype>& source_founder_phenotypes = source_deme.GetFounderPhenotypes();
         for(int i=0; i<source_founders.GetSize(); i++) {
+        
           int cellid = DemeSelectInjectionCell(source_deme, i);
+          //cout << "founder: " << source_founders[i] << endl;
           cGenotype * genotype = m_world->GetClassificationManager().FindGenotype(source_founders[i]);
-          assert(genotype);
-          InjectGenotype(cellid, genotype);
-          DemePostInjection(source_deme, cell_array[cellid]); 
+          InjectDemeFounder(cellid, *genotype, &source_founder_phenotypes[i]);
+          DemePostInjection(source_deme, cell_array[cellid]);
         }
+        
+        //cout << target_deme.GetOrgCount() << " target orgs." << endl;
+        //cout << source_deme.GetOrgCount() << " source orgs." << endl;
       }
       // source deme is left untouched
       else if (m_world->GetConfig().DEMES_DIVIDE_METHOD.Get() == 2) {
@@ -1591,7 +1763,45 @@
         m_world->GetDriver().RaiseFatalException(1, "Unknown DEMES_DIVIDE_METHOD");
       }
       
+      // Update *source* generations per lifetime by the founders we used to seed the *target*.
+      // and *source*, so that we average over them.
+      tArray<cPhenotype> new_phenotypes;
+      new_phenotypes = new_phenotypes + target_deme.GetFounderPhenotypes();
+      new_phenotypes = new_phenotypes + source_deme.GetFounderPhenotypes();
+      source_deme.UpdateGenerationsPerLifetime(new_phenotypes);
+      
+                        
       /*
+      // Debug Code
+      //// Count the number of orgs in each deme.
+      count = 0;
+      for(int i=0; i<target_deme.GetSize(); ++i) {
+        int cell_id = target_deme.GetCellID(i);
+        if(cell_array[cell_id].IsOccupied()) count++;
+      }
+      cout << "Final orgs in target deme: " << count << endl;
+
+      count = 0;
+      for(int i=0; i<source_deme.GetSize(); ++i) {
+        int cell_id = source_deme.GetCellID(i);
+        if(cell_array[cell_id].IsOccupied()) count++;
+      }
+      cout << "Final orgs in source deme: " << count << endl;
+
+      if (1) {
+        tArray<int>& source_founders = source_deme.GetFounderGenotypeIDs();
+        cGenotype * source_founder_genotype = m_world->GetClassificationManager().FindGenotype(source_founders[0]);
+        tArray<int>& target_founders = target_deme.GetFounderGenotypeIDs();
+        cGenotype * target_founder_genotype = m_world->GetClassificationManager().FindGenotype(target_founders[0]);
+        if (original_source_founder_genotype->GetGenome().AsString() != source_founder_genotype->GetGenome().AsString())
+        {
+          cout << "Original source founder does not equal final source founder!!!!" << endl;
+        }
+        
+        cout << "Source:" << endl << source_founder_genotype->GetGenome().AsString() << endl;
+        cout << "Target:" << endl << target_founder_genotype->GetGenome().AsString() << endl;
+      }
+      
       // Debug
       tArray<int>& new_source_founders = source_deme.GetFounders();
       cerr << "New source genotype ids:" << endl;
@@ -1670,7 +1880,47 @@
   }
 }
 
+void cPopulation::InjectDemeFounder(int _cell_id, cGenotype& _genotype, cPhenotype* _phenotype)
+{
+  // phenotype can be NULL
+  
+  InjectGenotype(_cell_id, &_genotype);
+  
+  // At this point, the cell had better be occupied...
+  assert(GetCell(_cell_id).IsOccupied());
+  cOrganism * organism = GetCell(_cell_id).GetOrganism();
 
+
+  //Now we need to set up the phenotype of this organism...
+  if (_phenotype) {
+    //If we want founders to have their proper phenotypes
+    // then we might do something like this... (untested)
+    //organism->SetPhenotype(*_phenotype);
+    // Re-initialize the time-slice for this new organism.
+    //AdjustSchedule(_cell_id, organism->GetPhenotype().GetMerit());
+
+    // For now, just copy the generation...
+    organism->GetPhenotype().SetGeneration( _phenotype->GetGeneration() );
+    
+    // and germline propensity.
+    organism->GetPhenotype().SetPermanentGermlinePropensity( _phenotype->GetPermanentGermlinePropensity()  );
+    
+    if (m_world->GetConfig().DEMES_FOUNDER_GERMLINE_PROPENSITY.Get() > 0.0) {
+      organism->GetPhenotype().SetPermanentGermlinePropensity( m_world->GetConfig().DEMES_FOUNDER_GERMLINE_PROPENSITY.Get() );
+    }
+  }
+  
+  /* It requires mcuh more than this to correctly implement, do later if needed @JEB
+  //Optionally, set the first organism's merit to a constant value
+  //actually, we need to add so the first organism is seeded this way too...
+  if (m_world->GetConfig().DEMES_DEFAULT_MERIT.Get()) {
+    organism->GetPhenotype().SetMerit( cMerit(m_world->GetConfig().DEMES_DEFAULT_MERIT.Get()) );
+    AdjustSchedule(GetCell(_cell_id), organism->GetPhenotype().GetMerit());
+  }
+  */
+}
+
+
 /*! Helper method that determines the cell into which an organism will be placed.
 Respects all of the different placement options that are relevant for deme replication.
 
@@ -2387,11 +2637,7 @@
   
     if(deme_array[i].IsEmpty()) continue;
     
-    tArray<int>& deme_founders = deme_array[i].GetFounders();   
-    
-    // this case really shouldn't happen, but starting
-    // orgs don't count as founders currently...
-    if (deme_founders.GetSize() == 0) continue;
+    tArray<int>& deme_founders = deme_array[i].GetFounderGenotypeIDs();   
       
     fp << i << " " << deme_founders.GetSize();    
     for(int j=0; j<deme_founders.GetSize(); j++) {  
@@ -2971,10 +3217,12 @@
   stats.SumDemeGestationTime().Clear();
   stats.SumDemeNormalizedTimeUsed().Clear();
   stats.SumDemeMerit().Clear();
-  
+
+  stats.SumDemeGenerationsPerLifetime().Clear();
+
   for(int i = 0; i < GetNumDemes(); i++) {
     cDeme& deme = GetDeme(i);
-    if(!deme.IsEmpty())  // ignore empty demes
+    if(deme.IsEmpty())  // ignore empty demes
     { 
       continue;
     }
@@ -2986,6 +3234,8 @@
     stats.SumDemeGestationTime().Add(deme.GetGestationTime());
     stats.SumDemeNormalizedTimeUsed().Add(deme.GetLastNormalizedTimeUsed());
     stats.SumDemeMerit().Add(deme.GetDemeMerit().GetDouble());
+    
+    stats.SumDemeGenerationsPerLifetime().Add(deme.GetGenerationsPerLifetime());
   }
 }
 
@@ -3622,20 +3872,43 @@
   
   LineageSetupOrganism(GetCell(cell_id).GetOrganism(), 0, lineage_label);
   
-  // If we're using germlines, then we have to be a little careful here.
-  // This should probably not be within Inject() since we mainly want it to
-  // apply to the START_CREATURE? -- @JEB
-	if(m_world->GetConfig().DEMES_USE_GERMLINE.Get() == 1) {
-		cDeme& deme = deme_array[GetCell(cell_id).GetDemeID()];
-		if(deme.GetGermline().Size()==0) {  
-			deme.GetGermline().Add(GetCell(cell_id).GetOrganism()->GetGenome());
-		}
-	}  
-  else if(m_world->GetConfig().DEMES_USE_GERMLINE.Get() == 2) {
-    //find the genotype we just created from the genome, and save it
-		cDeme& deme = deme_array[GetCell(cell_id).GetDemeID()];
-    cGenotype * genotype = m_world->GetClassificationManager().FindGenotype(genome, lineage_label);
-    deme.ReplaceGermline(*genotype);
+  if (GetNumDemes() > 1) {
+    cDeme& deme = deme_array[GetCell(cell_id).GetDemeID()];
+
+    // If we're using germlines, then we have to be a little careful here.
+    // This should probably not be within Inject() since we mainly want it to
+    // apply to the START_CREATURE? -- @JEB
+    
+    //@JEB This section is very messy to maintain consistency with other deme ways.
+    
+    if(m_world->GetConfig().DEMES_SEED_METHOD.Get() == 0) {
+      if(m_world->GetConfig().DEMES_USE_GERMLINE.Get() == 1) {
+        if(deme.GetGermline().Size()==0) {  
+          deme.GetGermline().Add(GetCell(cell_id).GetOrganism()->GetGenome());
+        }
+      }
+    }
+    else if(m_world->GetConfig().DEMES_SEED_METHOD.Get() == 1) {    
+      if(m_world->GetConfig().DEMES_USE_GERMLINE.Get() == 2) {
+        //find the genotype we just created from the genome, and save it
+        cGenotype * genotype = GetCell(cell_id).GetOrganism()->GetGenotype();
+        deme.ReplaceGermline(*genotype);        
+      } 
+      else { // not germlines, save org as founder
+        cGenotype * genotype = GetCell(cell_id).GetOrganism()->GetGenotype();
+        deme.AddFounder(*genotype, &phenotype);
+      }
+      
+      GetCell(cell_id).GetOrganism()->GetPhenotype().SetPermanentGermlinePropensity
+        (m_world->GetConfig().DEMES_FOUNDER_GERMLINE_PROPENSITY.Get());
+        
+        
+      if (m_world->GetConfig().DEMES_FOUNDER_GERMLINE_PROPENSITY.Get() > 0.0) {
+         GetCell(cell_id).GetOrganism()->GetPhenotype().SetPermanentGermlinePropensity
+          ( m_world->GetConfig().DEMES_FOUNDER_GERMLINE_PROPENSITY.Get() );
+      }
+
+    }
   }
 }
 
@@ -3929,6 +4202,7 @@
 void cPopulation::PrintPhenotypeData(const cString& filename)
 {
   set<int> ids;
+  set<cString> complete;
   
   for (int i = 0; i < cell_array.GetSize(); i++) {
     // Only look at cells with organisms in them.
@@ -3937,16 +4211,20 @@
     const cPhenotype& phenotype = cell_array[i].GetOrganism()->GetPhenotype();
     
     int id = 0;
+    cString key;
     for (int j = 0; j < phenotype.GetLastTaskCount().GetSize(); j++) {
       if (phenotype.GetLastTaskCount()[j] > 0) id += (1 << j);
+      key += cStringUtil::Stringf("%i-", phenotype.GetLastTaskCount()[j]);
     }
     ids.insert(id);
+    complete.insert(key);
   }
   
   cDataFile& df = m_world->GetDataFile(filename);
   df.WriteTimeStamp();
   df.Write(m_world->GetStats().GetUpdate(), "Update");
-  df.Write(static_cast<int>(ids.size()), "Unique Phenotypes");
+  df.Write(static_cast<int>(ids.size()), "Unique Phenotypes (by task done)");
+  df.Write(static_cast<int>(complete.size()), "Unique Phenotypes (by task count)");
   df.Endl();
 }
 

Modified: development/source/main/cPopulation.h
===================================================================
--- development/source/main/cPopulation.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cPopulation.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -204,6 +204,9 @@
   
   //! Helper method that seeds a target deme from the organisms in the source deme.
   void SeedDeme(cDeme& source_deme, cDeme& target_deme);
+
+  //! Helper method that adds a founder organism to a deme, and sets up its phenotype
+  void InjectDemeFounder(int _cell_id, cGenotype& _genotype, cPhenotype* _phenotype = NULL);
   
   //! Helper method that determines the cell into which an organism will be placed during deme replication.
   int DemeSelectInjectionCell(cDeme& deme, int sequence=0);

Modified: development/source/main/cReactionProcess.h
===================================================================
--- development/source/main/cReactionProcess.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cReactionProcess.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -55,6 +55,7 @@
   bool lethal;		 // Lethality of reaction
   bool sterilize; //!< Whether performance of this reaction sterilizes the organism.
   double deme_fraction; //!< Fraction of process reward that is applied to the organism's deme.
+  bool is_germline;         // Apply reward to germline propensity instead of bonus?
   cString match_string;	 // Bit string to match if this is a match string reaction
   int inst_id;           // Instruction to be triggered if reaction successful.
   bool depletable;       // Does completing consume resource?
@@ -83,6 +84,7 @@
     , lethal(0)
     , sterilize(false)
     , deme_fraction(0.0)
+    , is_germline(false)
     , inst_id(-1)
     , depletable(true)
     , detect(NULL)
@@ -105,6 +107,7 @@
   bool GetLethal() const { return lethal; }
   bool GetSterilize() const { return sterilize; }
   double GetDemeFraction() const { return deme_fraction; }
+  bool GetIsGermline() const { return is_germline; }
   cResource* GetDetect() const { return detect; }
   double GetDetectionThreshold() const { return detection_threshold; }
   double GetDetectionError() const { return detection_error; }
@@ -123,6 +126,7 @@
   void SetLethal(int _in) { lethal = _in; }
   void SetSterile(int _in) { sterilize = _in; }
   void SetDemeFraction(double _in) { assert(_in>=0.0); assert(_in<=1.0); deme_fraction = _in; }
+  void SetIsGermline(bool _in) { is_germline = _in; }
   void SetDetect(cResource* _in) { detect = _in; }
   void SetDetectionThreshold(double _in) { detection_threshold = _in; }
   void SetDetectionError(double _in) { detection_error = _in; }

Modified: development/source/main/cReactionResult.cc
===================================================================
--- development/source/main/cReactionResult.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cReactionResult.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -40,6 +40,8 @@
   , energy_add(0.0)
   , bonus_add(0.0)
   , bonus_mult(1.0)
+  , germline_add(0.0)
+  , germline_mult(1.0)
   , insts_triggered(0)
   , lethal(false)
   , sterilize(false)
@@ -152,6 +154,19 @@
   deme_mult_bonus *= value;
 }
 
+void cReactionResult::AddGermline(double value)
+{
+  ActivateReaction();
+  germline_add += value;
+}
+
+void cReactionResult::MultGermline(double value)
+{
+  ActivateReaction();
+  germline_mult *= value;
+}
+
+
 void cReactionResult::AddInst(int id)
 {
   insts_triggered.Push(id);

Modified: development/source/main/cReactionResult.h
===================================================================
--- development/source/main/cReactionResult.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cReactionResult.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -43,6 +43,8 @@
   double energy_add;
   double bonus_add;
   double bonus_mult;
+  double germline_add;
+  double germline_mult;
   tArray<int> insts_triggered;
   bool lethal;
   bool sterilize;
@@ -78,7 +80,9 @@
   void MultBonus(double value);
   void AddDemeBonus(double value);
   void MultDemeBonus(double value);
-  
+  void AddGermline(double value);
+  void MultGermline(double value);
+
   void AddInst(int id);
   
   double GetConsumed(int id);
@@ -97,6 +101,9 @@
   tArray<int>& GetInstArray() { return insts_triggered; }
   double GetAddDemeBonus() { return deme_add_bonus; }
   double GetMultDemeBonus() { return deme_mult_bonus; }
+  double GetAddGermline() { return germline_add; }
+  double GetMultGermline() { return germline_mult; }
+
 };
 
 

Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cStats.cc	2008-04-07 01:49:58 UTC (rev 2520)
@@ -584,6 +584,7 @@
   df.Write(sum_deme_merit.Average(),                        "Merit");
   df.Write(sum_deme_gestation_time.Average(),               "Gestation Time");
   df.Write(sum_deme_normalized_time_used.Average(),         "Time Used (normalized by org fitness)");
+  df.Write(sum_deme_generations_per_lifetime.Average(),     "Generations between current and last founders");
 
   df.Endl();
 }
@@ -1342,7 +1343,7 @@
   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
     cDeme& deme = m_world->GetPopulation().GetDeme(i);
     for(int j = 0; j < num_tasks; j++) {
-      df.Write( (deme.GetLastTaskCount()[j] > 0), cStringUtil::Stringf("%i.", i) + task_names[j] );
+      df.Write( (deme.GetLastTaskExeCount()[j] > 0), cStringUtil::Stringf("%i.", i) + task_names[j] );
     }
 	}
   df.Endl();
@@ -1362,7 +1363,7 @@
   for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
     cDeme& deme = m_world->GetPopulation().GetDeme(i);
     for(int j = 0; j < num_tasks; j++) {
-      df.Write( deme.GetLastTaskCount()[j], cStringUtil::Stringf("%i.", i) + task_names[j] );
+      df.Write( deme.GetLastTaskExeCount()[j], cStringUtil::Stringf("%i.", i) + task_names[j] );
     }
 	}
   df.Endl();
@@ -1387,3 +1388,64 @@
   df.Endl();
 }
 
+void cStats::PrintDemeOrgTasks(const cString& filename){
+  cDataFile& df = m_world->GetDataFile(filename);
+	df.WriteComment("Avida deme org tasks data");
+	df.WriteTimeStamp();
+	df.WriteComment("First column gives the current update, next columns give the number");
+	df.WriteComment("of organisms that have the particular task as a component of their merit");
+	df.WriteComment("in a particular deme when the deme last divided.");
+
+  const int num_tasks = m_world->GetEnvironment().GetNumTasks();
+
+	df.Write(m_update,   "Update");
+  for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+    cDeme& deme = m_world->GetPopulation().GetDeme(i);
+    for(int j = 0; j < num_tasks; j++) {
+      df.Write( deme.GetLastOrgTaskCount()[j], cStringUtil::Stringf("%i.", i) + task_names[j] );
+    }
+  }
+  df.Endl();
+}
+
+void cStats::PrintDemeOrgTasksExe(const cString& filename){
+  cDataFile& df = m_world->GetDataFile(filename);
+	df.WriteComment("Avida deme org tasks exe data");
+	df.WriteTimeStamp();
+	df.WriteComment("First column gives the current update, next columns give the number");
+	df.WriteComment("of times a task has contributed to the merit of all organisms");
+	df.WriteComment("in a particular deme when the deme last divided.");
+
+  const int num_tasks = m_world->GetEnvironment().GetNumTasks();
+
+	df.Write(m_update,   "Update");
+  for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+    cDeme& deme = m_world->GetPopulation().GetDeme(i);
+    for(int j = 0; j < num_tasks; j++) {
+      df.Write( deme.GetLastOrgTaskExeCount()[j], cStringUtil::Stringf("%i.", i) + task_names[j] );
+    }
+  }
+
+  df.Endl();
+}
+
+void cStats::PrintDemeOrgReactions(const cString& filename){
+  cDataFile& df = m_world->GetDataFile(filename);
+	df.WriteComment("Avida deme org reactions data");
+	df.WriteTimeStamp();
+  df.WriteComment("First column gives the current update, all further columns give the number");
+  df.WriteComment("of currently living organisms each reaction has affected");
+	df.WriteComment("in a particular deme when the deme last divided.");
+
+  const int num_reactions = m_world->GetEnvironment().GetReactionLib().GetSize();
+
+	df.Write(m_update,   "Update");
+  for(int i=0; i<m_world->GetPopulation().GetNumDemes(); ++i) {
+    cDeme& deme = m_world->GetPopulation().GetDeme(i);
+    for(int j = 0; j < num_reactions; j++) {
+      df.Write( deme.GetLastOrgReactionCount()[j], cStringUtil::Stringf("%i.", i) + m_world->GetEnvironment().GetReactionLib().GetReaction(j)->GetName()  );
+    }
+  }
+  df.Endl();
+}
+

Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h	2008-04-04 19:18:26 UTC (rev 2519)
+++ development/source/main/cStats.h	2008-04-07 01:49:58 UTC (rev 2520)
@@ -274,6 +274,7 @@
   cIntSum sum_deme_gestation_time;
   cDoubleSum sum_deme_normalized_time_used;
   cDoubleSum sum_deme_merit;
+  cDoubleSum sum_deme_generations_per_lifetime;
 
   // Speculative Execution Stats
   int m_spec_total;
@@ -418,7 +419,8 @@
   cIntSum& SumDemeGestationTime()   { return sum_deme_gestation_time; }
   cDoubleSum& SumDemeNormalizedTimeUsed()   { return sum_deme_normalized_time_used; }
   cDoubleSum& SumDemeMerit()   { return sum_deme_merit; }
-  
+  cDoubleSum& SumDemeGenerationsPerLifetime()   { return sum_deme_generations_per_lifetime; }
+
 #if INSTRUCTION_COUNT
   void ZeroInst();
 #endif
@@ -458,8 +460,8 @@
   const cIntSum& SumDemeGestationTime() const  { return sum_deme_generation; }
   const cDoubleSum& SumDemeNormalizedTimeUsed() const  { return sum_deme_normalized_time_used; }
   const cDoubleSum& SumDemeMerit()  const  { return sum_deme_merit; }
+  const cDoubleSum& SumDemeGenerationsPerLifetime() const  { return sum_deme_generations_per_lifetime; }
 
-
   void IncResamplings() { ++num_resamplings; }  // @AWC 06/29/06
   void IncFailedResamplings() { ++num_failedResamplings; }  // @AWC 06/29/06
 
@@ -722,8 +724,10 @@
   void PrintDemeTasks(const cString& filename);
   void PrintDemeTasksExe(const cString& filename);
   void PrintDemeReactions(const cString& filename);
-
-
+  void PrintDemeOrgTasks(const cString& filename);
+  void PrintDemeOrgTasksExe(const cString& filename);
+  void PrintDemeOrgReactions(const cString& filename);
+  
 protected:
   int m_deme_num_repls; //!< Number of deme replications since last PrintDemeReplicationData.
   cDoubleSum m_deme_gestation_time; //!< Gestation time for demes - mean age at deme replication.




More information about the Avida-cvs mailing list