[Avida-SVN] r1708 - in development: Avida.xcodeproj source/cpu source/main support/config

barrick at myxo.css.msu.edu barrick at myxo.css.msu.edu
Fri Jun 22 13:19:35 PDT 2007


Author: barrick
Date: 2007-06-22 16:19:35 -0400 (Fri, 22 Jun 2007)
New Revision: 1708

Modified:
   development/Avida.xcodeproj/project.pbxproj
   development/source/cpu/cHardwareBase.cc
   development/source/cpu/cHardwareBase.h
   development/source/cpu/cHardwareGX.cc
   development/source/cpu/cHardwareGX.h
   development/source/main/cAvidaConfig.h
   development/source/main/cOrganism.cc
   development/source/main/cOrganism.h
   development/support/config/avida.cfg
Log:
GX Update

1) Fixed some problems with how task input/output was being evaluated "separately" for programids.
2) "Easier" GX architectures with implicit gene expression and/or division possible.
3) Slip mutations causing deletions or duplications implemented for GX. Could be added to other architectures in DoMutations.



Modified: development/Avida.xcodeproj/project.pbxproj
===================================================================
--- development/Avida.xcodeproj/project.pbxproj	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/Avida.xcodeproj/project.pbxproj	2007-06-22 20:19:35 UTC (rev 1708)
@@ -796,7 +796,7 @@
 		DCC315CE076253A5008F7A48 /* environment.rotate */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = environment.rotate; sourceTree = "<group>"; };
 		DCC315D0076253A5008F7A48 /* task_event_gen.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = task_event_gen.cc; sourceTree = "<group>"; };
 		DCC315D1076253A5008F7A48 /* task_event_gen.old.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = task_event_gen.old.cc; sourceTree = "<group>"; };
-		DCC3164D07626CF3008F7A48 /* avida */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = avida; sourceTree = BUILT_PRODUCTS_DIR; };
+		DCC3164D07626CF3008F7A48 /* avida */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = avida; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */

Modified: development/source/cpu/cHardwareBase.cc
===================================================================
--- development/source/cpu/cHardwareBase.cc	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/source/cpu/cHardwareBase.cc	2007-06-22 20:19:35 UTC (rev 1708)
@@ -659,7 +659,17 @@
   return temp_head;
 }
 
+tBuffer<int>& cHardwareBase::GetInputBuf() 
+{ 
+  return organism->GetInputBuf();
+}
 
+tBuffer<int>& cHardwareBase::GetOutputBuf() 
+{ 
+  return organism->GetOutputBuf(); 
+}
+
+
 bool cHardwareBase::Inst_Nop(cAvidaContext& ctx)          // Do Nothing.
 {
   return true;

Modified: development/source/cpu/cHardwareBase.h
===================================================================
--- development/source/cpu/cHardwareBase.h	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/source/cpu/cHardwareBase.h	2007-06-22 20:19:35 UTC (rev 1708)
@@ -29,6 +29,10 @@
 #include <cassert>
 #include <iostream>
 
+#ifndef tBuffer_h
+#include "tBuffer.h"
+#endif
+
 using namespace std;
 
 class cAvidaContext;
@@ -155,8 +159,11 @@
   virtual int PointMutate(cAvidaContext& ctx, const double mut_rate);
   virtual bool TriggerMutations(cAvidaContext& ctx, int trigger);
   virtual bool TriggerMutations(cAvidaContext& ctx, int trigger, cHeadCPU& cur_head);
+
+  // --------  Input/Output Buffers  --------
+  virtual tBuffer<int>& GetInputBuf();
+  virtual tBuffer<int>& GetOutputBuf();
   
-  
 protected:
   // --------  No-Operation Instruction --------
   bool Inst_Nop(cAvidaContext& ctx);  // A no-operation instruction that does nothing! 

Modified: development/source/cpu/cHardwareGX.cc
===================================================================
--- development/source/cpu/cHardwareGX.cc	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/source/cpu/cHardwareGX.cc	2007-06-22 20:19:35 UTC (rev 1708)
@@ -43,7 +43,6 @@
 #include "cWorld.h"
 #include "tInstLibEntry.h"
 
-
 using namespace std;
 
 //! A small helper struct to make deleting a little easier.
@@ -53,7 +52,7 @@
 
 
 tInstLib<cHardwareGX::tMethod>* cHardwareGX::s_inst_slib = cHardwareGX::initInstLib();
-const double cHardwareGX::EXECUTABLE_COPY_PROCESSIVITY = 0.97;
+const double cHardwareGX::EXECUTABLE_COPY_PROCESSIVITY = 1.0;
 const double cHardwareGX::READABLE_COPY_PROCESSIVITY = 1.0;
 
 tInstLib<cHardwareGX::tMethod>* cHardwareGX::initInstLib(void)
@@ -241,7 +240,9 @@
     tInstLibEntry<tMethod>("h-copy8", &cHardwareGX::Inst_HeadCopy8),
     tInstLibEntry<tMethod>("h-copy9", &cHardwareGX::Inst_HeadCopy9),
     tInstLibEntry<tMethod>("h-copy10", &cHardwareGX::Inst_HeadCopy10),
-        
+
+    tInstLibEntry<tMethod>("repro", &cHardwareGX::Inst_Repro),
+
     tInstLibEntry<tMethod>("spawn-deme", &cHardwareGX::Inst_SpawnDeme),
     
     // Suicide
@@ -264,18 +265,22 @@
     tInstLibEntry<tMethod>("if-bind", &cHardwareGX::Inst_IfBind),
     tInstLibEntry<tMethod>("if-bind2", &cHardwareGX::Inst_IfBind2),
     tInstLibEntry<tMethod>("num-sites", &cHardwareGX::Inst_NumSites),
-    
-    tInstLibEntry<tMethod>("p-get", &cHardwareGX::Inst_ProgramidGet),
-    tInstLibEntry<tMethod>("p-put", &cHardwareGX::Inst_ProgramidPut),
 
+    tInstLibEntry<tMethod>("i-alloc", &cHardwareGX::Inst_ProgramidImplicitAllocate),
+    tInstLibEntry<tMethod>("i-divide", &cHardwareGX::Inst_ProgramidImplicitDivide),
+
+    tInstLibEntry<tMethod>("promoter", &cHardwareGX::Inst_Promoter),
+    tInstLibEntry<tMethod>("terminator", &cHardwareGX::Inst_Terminator),
+    tInstLibEntry<tMethod>("regulate", &cHardwareGX::Inst_HeadRegulate),
+    tInstLibEntry<tMethod>("end", &cHardwareGX::Inst_EndProgramidExecution),
+
     // These are dummy instructions used for making mutiple programids
     // look like one genome (for purposes of passing to offspring and printing).
-    // They need to be included but should have ZERO probabilities!!!
+    // They need to be included for the full GX model but should have ZERO probabilities!!!
     tInstLibEntry<tMethod>("PROGRAMID", &cHardwareGX::Inst_Nop),
     tInstLibEntry<tMethod>("READABLE", &cHardwareGX::Inst_Nop),
     tInstLibEntry<tMethod>("BINDABLE", &cHardwareGX::Inst_Nop),
-    tInstLibEntry<tMethod>("EXECUTABLE", &cHardwareGX::Inst_Nop)
-    
+    tInstLibEntry<tMethod>("EXECUTABLE", &cHardwareGX::Inst_Nop),
   };
   
   const int n_size = sizeof(s_n_array)/sizeof(cNOPEntryCPU);
@@ -325,35 +330,68 @@
   // Clear the current list of programids.
   std::for_each(m_programids.begin(), m_programids.end(), delete_functor());
   m_programids.clear(); 
+
+  // Using the "full" gene expression setup.  All programid creation is explicit.
+  if (m_world->GetConfig().IMPLICIT_GENE_EXPRESSION.Get() == 0)
+  {
  
-  // And add any programids specified by the "genome."
-  cGenome genome = organism->GetGenome();
-  
-  // These specify the range of instructions that will be used to create a new
-  // programid.  The range of instructions used to create a programid is:
-  // [begin, end), that is, the instruction pointed to by end is *not* copied.
-  cInstruction* begin=&genome[0];
-  cInstruction* end=&begin[genome.GetSize()];
-  cInstruction* i=0;
-  // Find the first instance of a PROGRAMID instruction.
-  begin = std::find_if(begin, end, bind2nd(equal_to<cInstruction>(), GetInstSet().GetInst("PROGRAMID")));
-  while(begin!=end) {
-    // Find the boundary of this programid.
-    i = std::find_if(begin+1, end, bind2nd(equal_to<cInstruction>(), GetInstSet().GetInst("PROGRAMID")));
-    AddProgramid(new cProgramid(cGenome(begin, i), this));
-    begin = i;
+    // And add any programids specified by the "genome."
+    cGenome genome = organism->GetGenome();
+    
+    // These specify the range of instructions that will be used to create a new
+    // programid.  The range of instructions used to create a programid is:
+    // [begin, end), that is, the instruction pointed to by end is *not* copied.
+    cInstruction* begin=&genome[0];
+    cInstruction* end=&begin[genome.GetSize()];
+    cInstruction* i=0;
+    // Find the first instance of a PROGRAMID instruction.
+    begin = std::find_if(begin, end, bind2nd(equal_to<cInstruction>(), GetInstSet().GetInst("PROGRAMID")));
+    while(begin!=end) {
+      // Find the boundary of this programid.
+      i = std::find_if(begin+1, end, bind2nd(equal_to<cInstruction>(), GetInstSet().GetInst("PROGRAMID")));
+      AddProgramid(new cProgramid(cGenome(begin, i), this));
+      begin = i;
+    }
+    
+    assert(m_programids.size()>0);  
+    
+    // Sanity, oh, where is my sanity?
+    bool has_executable=false;
+    bool has_bindable=false;
+    for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end(); ++i) {
+      has_executable = has_executable || (*i)->GetExecutable();
+      has_bindable = has_bindable || (*i)->GetBindable();
+    }
+    assert(has_bindable && has_executable);
   }
+  else // Implicit RNAP GX Model. Executable programids created from genome.
+  {
+    m_recycle_state = 0.0;
+    // Optimization -- don't actually need a programid for the genome in the double implicit model.
+    // In the implicit model, we create one genome programid as the first memory space
+    programid_ptr p = new cProgramid(organism->GetGenome(), this);
+    p->SetReadable(true);
+    AddProgramid(p);
   
-  assert(m_programids.size()>0);  
-  
-  // Sanity, oh, where is my sanity?
-  bool has_executable=false;
-  bool has_bindable=false;
-  for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end(); ++i) {
-    has_executable = has_executable || (*i)->GetExecutable();
-    has_bindable = has_bindable || (*i)->GetBindable();
+    // Initialize the promoter state and rates
+    m_promoter_sum = 0.0; // We need to make sure that at least one position has a non-zero rate 
+    m_promoter_update_head.Reset(this,0);
+    m_promoter_update_head.Set(0);
+    m_promoter_rates.ResizeClear( organism->GetGenome().GetSize() );
+    m_promoter_states.ResizeClear( organism->GetGenome().GetSize() );
+    
+    cInstruction promoter_inst = GetInstSet().GetInst(cStringUtil::Stringf("promoter"));
+    do {
+      m_promoter_rates[m_promoter_update_head.GetPosition()] = 
+        (m_promoter_update_head.GetInst() == promoter_inst) ? 1 : m_world->GetConfig().IMPLICIT_BG_PROMOTER_RATE.Get();
+      m_promoter_sum += m_promoter_rates[m_promoter_update_head.GetPosition()];
+      m_promoter_states[m_promoter_update_head.GetPosition()] = 0.0;
+      m_promoter_update_head++;
+    } while (m_promoter_update_head.GetPosition() != 0);
+    
+    // \todo implement different initial conditions for created executable programids
+    ProcessImplicitGeneExpression(); 
   }
-  assert(has_bindable && has_executable);
   
   m_current = m_programids.back();
   m_mal_active = false;
@@ -372,7 +410,6 @@
 #endif
 }
 
-
 /*! In cHardwareGX, SingleProcess is something of a misnomer.  Each time this method
   is called, each cProgramid executes a single instruction.
   */
@@ -380,6 +417,18 @@
 {
   cPhenotype& phenotype = organism->GetPhenotype();
 
+  // Turn over programids if using the implicit model
+  if ( m_world->GetConfig().IMPLICIT_GENE_EXPRESSION.Get() )
+  {
+    m_recycle_state += (double)m_world->GetConfig().IMPLICIT_TURNOVER_RATE.Get();
+    while (m_recycle_state >= 1.0)
+    {
+      if (m_programids.size() > 1) RemoveProgramid(1);
+      m_recycle_state -= 1.0;
+    }
+    ProcessImplicitGeneExpression();
+  }
+    
   organism->SetRunning(true);
   m_just_divided = false;
   phenotype.IncTimeUsed();
@@ -391,7 +440,7 @@
   for(programid_list::iterator i=runnable.begin(); i!=runnable.end(); ++i) {
     // Currently executing programid.
     m_current = *i;
-    
+        
     // Print the status of this CPU at each step...
     if (m_tracer != NULL) m_tracer->TraceHardware(*this);
     
@@ -410,30 +459,14 @@
       
       // Break out if we just divided b/c the number of programids 
       // will have changed and it won't be obvious how to continue
+      // @JEB this organism may also have been replaced by its child,
+      // so we will not be able to continue safely!
       if (m_just_divided) break;
       
       if (m_advance_ip == true) { 
         IP().Advance();
       }
       
-      if (m_reset_inputs) {
-        // Re-randomize the inputs
-        organism->GetOrgInterface().ResetInputs(ctx); 
-        // And clear the current input buffer
-        m_current->m_inputBuffer.Clear();     
-      }
-     
-      if (m_reset_heads)
-      {
-        // Set the read and write heads back to ourself
-        cHeadProgramid& write = GetHead(nHardware::HEAD_WRITE);
-        cHeadProgramid& read = GetHead(nHardware::HEAD_READ);      
-        read.GetProgramid()->RemoveContactingHead(read);
-        read.Set(0, m_current->m_id);     
-        write.GetProgramid()->RemoveContactingHead(write);
-        write.Set(0, m_current->m_id);                                      
-      }
-      
       // Update this programid stat
       m_current->IncCPUCyclesUsed();  
     }
@@ -443,7 +476,8 @@
   // Now kill old programids.
   unsigned int on_p = 0;
   while(on_p < m_programids.size()) {
-    if(m_programids[on_p]->GetCPUCyclesUsed() > MAX_PROGRAMID_AGE) {
+    if( (m_programids[on_p]->GetCPUCyclesUsed() > m_world->GetConfig().MAX_PROGRAMID_AGE.Get())
+      || m_programids[on_p]->m_marked_for_death) {
       RemoveProgramid(on_p);
     } else {
       on_p++;
@@ -468,6 +502,12 @@
   }
   
   organism->SetRunning(false);
+  
+  //Implicit Divide (for organisms that divide every so often with repro)
+  if (m_world->GetConfig().IMPLICIT_REPRO_TIME.Get() && (phenotype.GetCPUCyclesUsed() >= m_world->GetConfig().IMPLICIT_REPRO_TIME.Get()))
+  {
+    Inst_Repro(ctx);
+  }
 }
 
 //  const int num_threads = GetNumThreads();
@@ -617,7 +657,7 @@
 {
   bool result = true;
   for(programid_list::iterator i=m_programids.begin(); i!=m_programids.end() && result; ++i) {
-    result = result && (*i)->m_memory.OK() && (*i)->m_stack.OK() && (*i)->m_nextLabel.OK();
+    result = result && (*i)->m_memory.OK() && (*i)->m_stack.OK() && (*i)->m_next_label.OK();
   }
   return result;
 }
@@ -651,7 +691,7 @@
     << "F-Head:" << GetHead(nHardware::HEAD_FLOW).GetMemSpace() << ":" << GetHead(nHardware::HEAD_FLOW).GetPosition() << "  "
     << "RL:" << GetReadLabel().AsString() << "   "
     << endl;
-
+   
 // This will have to be revisited soon.
 //  int number_of_stacks = GetNumStacks();
 //  for (int stack_id = 0; stack_id < number_of_stacks; stack_id++) {
@@ -1187,11 +1227,28 @@
   return true;
 }
 
+int cHardwareGX::GetExecutedSize(const int parent_size)
+{
+/* @JEB - not really relevant to GX
+  int executed_size = 0;
+  const cCPUMemory& memory = GetMemory();
+  for (int i = 0; i < parent_size; i++) {
+    if (memory.FlagExecuted(i)) executed_size++;
+  }  
+  return executed_size;
+*/
+  return parent_size;
+}
+
 int cHardwareGX::GetCopiedSize(const int parent_size, const int child_size)
 {
+  if (m_world->GetConfig().IMPLICIT_REPRO_TIME.Get()) return parent_size;
+
   int copied_size = 0;
-  const cCPUMemory& memory = GetMemory();
-  for (int i = parent_size; i < parent_size + child_size; i++) {
+  //@JEB - we care about how much has been copied by the current programid
+  // parent_size and child_size are not relevant!
+  const cCPUMemory& memory = m_programids[GetHead(nHardware::HEAD_WRITE).GetMemSpace()]->GetMemory();
+  for (int i = 0; i < memory.GetSize(); i++) {
     if (memory.FlagCopied(i)) copied_size++;
   }
   return copied_size;
@@ -1207,12 +1264,6 @@
 */
 bool cHardwareGX::Divide_Main(cAvidaContext& ctx)
 {
-  
-//  if(m_current->TriggerReplication()) {
-//  } else {
-//  }
-//  
-  
 //  const int child_size = GetMemory().GetSize() - div_point - extra_lines;
 //  
 //  // Make sure this divide will produce a viable offspring.
@@ -2062,7 +2113,61 @@
   } else return false;
 }
 
+bool cHardwareGX::Inst_Repro(cAvidaContext& ctx)
+{
+  // Setup child
+  cCPUMemory& child_genome = organism->ChildGenome();
+  child_genome = organism->GetGenome();
+  organism->GetPhenotype().SetLinesCopied(GetMemory().GetSize());
+  
+  // SLIPPAGE MUTATIONS
+  if ( ctx.GetRandom().P(m_world->GetConfig().DIVIDE_SLIP_PROB.Get()) )
+  {
+    int from = ctx.GetRandom().GetInt(organism->GetGenome().GetSize());
+    int to = ctx.GetRandom().GetInt(organism->GetGenome().GetSize());
 
+    //Resize child genome
+    child_genome.Resize( child_genome.GetSize() + (from-to) );
+    for (int i=0; i < organism->GetGenome().GetSize() - to; i++) 
+    {
+      child_genome[from+i] = (organism->GetGenome())[to+i];
+    }
+  }
+  
+  Divide_DoMutations(ctx);
+    
+  bool viable = Divide_CheckViable(ctx, organism->GetGenome().GetSize(), child_genome.GetSize());
+  //if the offspring is not viable (due to splippage mutations), then what do we do?
+  if (viable == false) return false;
+  
+  // Many tests will require us to run the offspring through a test CPU;
+  // this is, for example, to see if mutations need to be reverted or if
+  // lineages need to be updated.
+  Divide_TestFitnessMeasures(ctx);
+  
+#if INSTRUCTION_COSTS
+  // reset first time instruction costs
+  for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+    inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
+  }
+#endif
+  
+  if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+    m_advance_ip = false;
+  }
+  
+  // Activate the child
+  bool parent_alive = organism->ActivateDivide(ctx);
+
+  // Do more work if the parent lives through the birth of the offspring
+  if (parent_alive) {
+    if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) Reset();
+  }
+
+  m_just_divided = true;
+  return true;
+}
+
 bool cHardwareGX::Inst_SpawnDeme(cAvidaContext& ctx)
 {
   organism->SpawnDeme();
@@ -2159,12 +2264,13 @@
 }
 
 
+
 bool cHardwareGX::Inst_TaskGet(cAvidaContext& ctx)
 {
   const int reg_used = FindModifiedRegister(REG_CX);
-  const int value = organism->GetNextInput();
+  const int value = organism->GetNextInput(m_current->m_input_pointer);
   GetRegister(reg_used) = value;
-  organism->DoInput(value);
+  organism->DoInput(m_current->m_input_buf, m_current->m_output_buf, value);  // Check for tasks completed.
   return true;
 }
 
@@ -2175,20 +2281,20 @@
 {
   // Randomize the inputs so they can't save numbers
   organism->GetOrgInterface().ResetInputs(ctx);   // Now re-randomize the inputs this organism sees
-  m_current->m_inputBuffer.Clear();
+  m_current->m_input_buf.Clear();
   //organism->ClearInput();                         // Also clear their input buffers, or they can still claim
                                                   // rewards for numbers no longer in their environment!
 
   const int reg_used_1 = FindModifiedRegister(REG_BX);
   const int reg_used_2 = FindNextRegister(reg_used_1);
   
-  const int value1 = organism->GetNextInput();
+  const int value1 = organism->GetNextInput(m_current->m_input_pointer);;
   GetRegister(reg_used_1) = value1;
-  organism->DoInput(value1);
+  organism->DoInput(m_current->m_input_buf, m_current->m_output_buf, value1); 
   
-  const int value2 = organism->GetNextInput();
+  const int value2 = organism->GetNextInput(m_current->m_input_pointer);;
   GetRegister(reg_used_2) = value2;
-  organism->DoInput(value2);
+  organism->DoInput(m_current->m_input_buf, m_current->m_output_buf, value2); 
   
   // Clear the task number
   organism->GetPhenotype().ClearEffTaskCount();
@@ -2198,9 +2304,9 @@
 
 bool cHardwareGX::Inst_TaskStackGet(cAvidaContext& ctx)
 {
-  const int value = organism->GetNextInput();
+  const int value = organism->GetNextInput(m_current->m_input_pointer);
   StackPush(value);
-  organism->DoInput(value);
+  organism->DoInput(m_current->m_input_buf, m_current->m_output_buf, value); 
   return true;
 }
 
@@ -2208,7 +2314,7 @@
 {
   // @DMB - TODO: this should look at the input_size...
   for (int i = 0; i < 3; i++) 
-    StackPush( organism->GetNextInput() );
+    StackPush( organism->GetNextInput(m_current->m_input_pointer) );
   return true;
 }
 
@@ -2225,7 +2331,7 @@
 {
   bool return_value = Inst_TaskPut(ctx);          // Do a normal put
   organism->GetOrgInterface().ResetInputs(ctx);   // Now re-randomize the inputs this organism sees
-  m_current->m_inputBuffer.Clear();               // Also clear their input buffers, or they can still claim
+  m_current->m_input_buf.Clear();               // Also clear their input buffers, or they can still claim
                                                   // rewards for numbers no longer in their environment!
   return return_value;
 }
@@ -2236,12 +2342,12 @@
   
   // Do the "put" component
   const int value_out = GetRegister(reg_used);
-  organism->DoOutput(ctx, m_current->m_inputBuffer, m_current->m_outputBuffer, value_out);  // Check for tasks completed.
+  organism->DoOutput(ctx, m_current->m_input_buf, m_current->m_output_buf, value_out);  // Check for tasks completed.
   
   // Do the "get" component
-  const int value_in = organism->GetNextInput();
+  const int value_in = organism->GetNextInput(m_current->m_input_pointer);
   GetRegister(reg_used) = value_in;
-  organism->DoInput(value_in);
+  organism->DoInput(m_current->m_input_buf, m_current->m_output_buf, value_in);  // Check for tasks completed.
   return true;
 }
 
@@ -2254,7 +2360,7 @@
   
   // Do the "put" component
   const int value_out = GetRegister(reg_used);
-  organism->DoOutput(ctx, m_current->m_inputBuffer, m_current->m_outputBuffer, value_out);  // Check for tasks completed.
+  organism->DoOutput(ctx, m_current->m_input_buf, m_current->m_output_buf, value_out);  // Check for tasks completed.
   
   //check cur_merit after the output
   double postOutputBonus = organism->GetPhenotype().GetCurBonus(); 
@@ -2275,9 +2381,9 @@
   }
   
   // Do the "get" component
-  const int value_in = organism->GetNextInput();
+  const int value_in = organism->GetNextInput(m_current->m_input_pointer);
   GetRegister(reg_used) = value_in;
-  organism->DoInput(value_in);
+  organism->DoInput(m_current->m_input_buf, m_current->m_output_buf, value_in);  // Check for tasks completed.
   return true;
 }
 
@@ -3125,6 +3231,10 @@
   GetHead(head_id).Adjust();
   sCPUStats & cpu_stats = organism->CPUStats();
   
+    // <--- GX addition
+  if ( !m_programids[GetHead(head_id).GetMemSpace()]->GetReadable() ) return false;
+  // --->
+  
   // Mutations only occur on the read, for the moment.
   int read_inst = 0;
   if (organism->TestCopyMut(ctx)) {
@@ -3147,6 +3257,10 @@
   const int head_id = FindModifiedHead(nHardware::HEAD_WRITE);
   cHeadCPU& active_head = GetHead(head_id);
   
+  // <--- GX addition
+  if ( !m_programids[GetHead(head_id).GetMemSpace()]->GetReadable() ) return false;
+  // --->
+  
   active_head.Adjust();
   
   int value = GetRegister(src);
@@ -3258,7 +3372,6 @@
   return true;
 }
 
-
 /*! This instruction allocates a new programid with a zero length genome
 and moves the write head of the current programid to it.
 */
@@ -3274,18 +3387,8 @@
   GetHead(nHardware::HEAD_WRITE).Set(0, m_current->m_id); // Immediately set the write head back to itself
   
   // If we've reached a programid limit, then deal with that
+  if ( (int)m_programids.size() >= m_world->GetConfig().MAX_PROGRAMIDS.Get() ) {
   
-  // \todo Keep track of total programid length as it is allocated
-  // rather than adding it back up every time we hit this code
-  // Technically, this currently counts incorrectly (depending on your POV) because
-  // p-copy leaves a blank instruction in the spot where it is going to write next.
-  int used_length = 0;
-  for (unsigned int i=0; i<m_programids.size(); i++) {
-    used_length += m_programids[i]->GetMemory().GetSize();
-  }
-
-  if ( (m_programids.size() >= MAX_PROGRAMIDS) || (used_length > MAX_PROGRAMID_TOTAL_LENGTH) ) {
-  
     //Decide on a programid to destroy, currently highest number of cpu cycles executed
     //\todo more methods of choosing..
   
@@ -3534,11 +3637,12 @@
   
   // \todo The timing of deletion, change, insertion mutation checks matters
   // I'm not sure this is right @JEB
-    
+  
+  bool ret = true;
   // Normal h-copy, unless a deletion occured
   if (!organism->TestCopyDel(ctx)) {
       // Normal h-copy
-    bool ret = Inst_HeadCopy(ctx);
+    ret = Inst_HeadCopy(ctx);
   }
   
   // Divide Insertion
@@ -3593,10 +3697,9 @@
   double terminate_p =  1 - ((m_programids[read.GetMemSpace()]->GetReadable()) ? READABLE_COPY_PROCESSIVITY : EXECUTABLE_COPY_PROCESSIVITY);
   if ( ctx.GetRandom().P(terminate_p) ) m_reset_heads = true;
   
-  return true;
+  return ret;
 }
 
-
 /*! This instruction creates a new organism by randomly dividing the programids with
 the daughter cell. Currently we convert the daughter genomes back into one list with pseudo-instructions
 telling us where new programids start and some of their properties. This is pretty inefficient.
@@ -3607,7 +3710,6 @@
   m_reset_inputs = true;
 
   //This stuff is usually set by Divide_CheckViable, leaving it zero causes problems
-  cPhenotype& phenotype = organism->GetPhenotype();
   organism->GetPhenotype().SetLinesExecuted(1);
   organism->GetPhenotype().SetLinesCopied(1);
   
@@ -3761,20 +3863,157 @@
   return true;
 }
 
-bool cHardwareGX::Inst_ProgramidGet(cAvidaContext& ctx)
+/* Implicit RNAP Model
+Allocate a new genome programid and place the write head on it.
+*/
+bool cHardwareGX::Inst_ProgramidImplicitAllocate(cAvidaContext& ctx)
 {
-  m_reset_heads = true;
-  return Inst_TaskGet(ctx);
+  const int dst = REG_BX;
+  const int cur_size = m_programids[0]->GetMemory().GetSize();
+  const int old_size = cur_size;
+  const int allocated_size = Min((int) (m_world->GetConfig().CHILD_SIZE_RANGE.Get() * cur_size), MAX_CREATURE_SIZE);
+  
+  // Modified Allocate_Main()
+    // must do divide before second allocate & must allocate positive amount...
+  if (m_world->GetConfig().REQUIRE_ALLOCATE.Get() && m_mal_active == true) {
+    organism->Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR, "Allocate already active");
+    return false;
+  }
+  if (allocated_size < 1) {
+    organism->Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+          cStringUtil::Stringf("Allocate of %d too small", allocated_size));
+    return false;
+  }
+  
+  
+  const int max_alloc_size = (int) (old_size * m_world->GetConfig().CHILD_SIZE_RANGE.Get());
+  if (allocated_size > max_alloc_size) {
+    organism->Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+          cStringUtil::Stringf("Allocate too large (%d > %d)",
+                               allocated_size, max_alloc_size));
+    return false;
+  }
+
+  const int max_old_size =
+    (int) (allocated_size * m_world->GetConfig().CHILD_SIZE_RANGE.Get());
+  if (old_size > max_old_size) {
+    organism->Fault(FAULT_LOC_ALLOC, FAULT_TYPE_ERROR,
+          cStringUtil::Stringf("Allocate too small (%d > %d)",
+                               old_size, max_old_size));
+    return false;
+  }
+  
+  cGenome new_genome(allocated_size);
+  programid_ptr new_programid = new cProgramid(new_genome, this);
+  new_programid->SetBindable(true);
+  new_programid->SetReadable(true);
+  AddProgramid(new_programid);
+
+/*  switch (m_world->GetConfig().ALLOC_METHOD.Get()) {
+    case ALLOC_METHOD_NECRO:
+      // Only break if this succeeds -- otherwise just do random.
+      if (Allocate_Necro(new_size) == true) break;
+    case ALLOC_METHOD_RANDOM:
+      Allocate_Random(ctx, old_size, new_size);
+      break;
+    case ALLOC_METHOD_DEFAULT:
+      Allocate_Default(new_size);
+      break;
+  } */
+  m_mal_active = true;
+  //--> End modified Main_Alloc
+
+  // Set the write head to the newly allocated programid
+  GetHead(nHardware::HEAD_WRITE).Set(0, new_programid->GetID());
+  // Set the read head to the first programid (=current genome)
+  GetHead(nHardware::HEAD_READ).Set(0, 0);
+  GetRegister(dst) = cur_size;
+
+  return true;
 }
 
-bool cHardwareGX::Inst_ProgramidPut(cAvidaContext& ctx)
+/* Implicit RNAP Model
+Create a new organism with a genome based on the current position
+of th write head.
+*/
+bool cHardwareGX::Inst_ProgramidImplicitDivide(cAvidaContext& ctx)
 {
-  m_reset_inputs = true;
-  m_reset_heads = true;
-  return Inst_TaskPut(ctx);
+  cHeadProgramid write_head = GetHead(nHardware::HEAD_WRITE);
+  int child_end =  GetHead(nHardware::HEAD_WRITE).GetPosition();
+
+  // Make sure this divide will produce a viable offspring.
+  const bool viable = Divide_CheckViable(ctx, organism->GetGenome().GetSize(), child_end);
+  if (viable == false) return false;
+
+  // Since the divide will now succeed, set up the information to be sent
+  // to the new organism
+  cGenome & child_genome = organism->ChildGenome();
+  child_genome = m_programids[write_head.GetMemSpace()]->GetMemory();
+  child_genome = cGenomeUtil::Crop(child_genome, 0, child_end);
+
+
+  // Handle Divide Mutations...
+  Divide_DoMutations(ctx);
+  
+  // Many tests will require us to run the offspring through a test CPU;
+  // this is, for example, to see if mutations need to be reverted or if
+  // lineages need to be updated.
+  Divide_TestFitnessMeasures(ctx);
+  
+#if INSTRUCTION_COSTS
+  // reset first time instruction costs
+  for (int i = 0; i < inst_ft_cost.GetSize(); i++) {
+    inst_ft_cost[i] = m_inst_set->GetFTCost(cInstruction(i));
+  }
+#endif
+  
+  m_mal_active = false;
+  if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) {
+    m_advance_ip = false;
+  }
+  
+  // Activate the child
+  bool parent_alive = organism->ActivateDivide(ctx);
+
+  // Do more work if the parent lives through the birth of the offspring
+  if (parent_alive) {
+    if (m_world->GetConfig().DIVIDE_METHOD.Get() == DIVIDE_METHOD_SPLIT) Reset();
+  }
+  
+  m_just_divided = true;
+  return true;
 }
 
+bool cHardwareGX::Inst_EndProgramidExecution(cAvidaContext& ctx)
+{
+  m_current->m_marked_for_death = true; //Mark us for death
+  return true;
+}
 
+/* Full Implict Model*/
+
+bool cHardwareGX::Inst_Promoter(cAvidaContext& ctx)
+{
+  // Promoters don't do anything themselves
+  return true;
+}
+
+bool cHardwareGX::Inst_Terminator(cAvidaContext& ctx)
+{
+  // Terminators don't do anything themselves
+  return true;
+}
+
+/*
+Place the write head of this programid on the next available match
+in the genome. Update promoter rates.
+*/
+bool cHardwareGX::Inst_HeadRegulate(cAvidaContext& ctx)
+{
+  return true;
+}
+
+
 //! Adds a new programid to the current cHardwareGX.
 void cHardwareGX::AddProgramid(programid_ptr programid) 
 { 
@@ -3792,11 +4031,23 @@
   
   programid_ptr save=m_current;  
   m_current = m_programids[remove_index];
+
+  if (m_world->GetVerbosity() >= VERBOSE_DETAILS)
+  {
+    cout << "Programid removed. Start position = " << m_current->GetHead(nHardware::HEAD_READ).GetPosition();
+    cout << " length = " <<  m_current->m_memory.GetSize() << endl;
+  }
+
   unsigned int write_head_contacted = (unsigned int)GetHead(nHardware::HEAD_WRITE).GetMemSpace();
   
   // First update the contacting head count for any cProgramids the heads 
   // of the programid to be removed might have been on
-  m_current->Detach();
+  
+  // The contacting head count is not used in the implicit model (and will be incorrect)
+  
+  if (!m_world->GetConfig().IMPLICIT_GENE_EXPRESSION.Get()) m_current->Detach();
+
+
 //  m_programids[GetHead(nHardware::HEAD_READ).GetMemSpace()]->RemoveContactingHead(GetHead(nHardware::HEAD_READ));
 //  m_programids[GetHead(nHardware::HEAD_WRITE).GetMemSpace()]->RemoveContactingHead(GetHead(nHardware::HEAD_WRITE));
 
@@ -3833,51 +4084,148 @@
 }
 
 
+void cHardwareGX::ProcessImplicitGeneExpression(int in_limit) 
+{
+  // If organism has no active promoters, catch us before we enter an infinite loop...
+  if (m_promoter_sum == 0.0) return;
+
+  static cInstruction terminator_inst = GetInstSet().GetInst(cStringUtil::Stringf("terminator"));
+
+  if (in_limit == -1 ) in_limit = m_world->GetConfig().MAX_PROGRAMIDS.Get();
+  
+  // Create executable programids up to the limit
+  const int genome_size = m_programids[m_promoter_update_head.GetMemSpace()]->GetMemory().GetSize();
+  const int inc = Min(genome_size, m_world->GetConfig().IMPLICIT_MAX_PROGRAMID_LENGTH.Get());
+
+  while ( m_programids.size() < (unsigned int)in_limit )
+  {
+    // Update promoter states according to rates until one fires
+    
+    while ( m_promoter_states[m_promoter_update_head.GetPosition()] < 1.0)
+    {
+      m_promoter_states[m_promoter_update_head.GetPosition()] += m_promoter_rates[m_promoter_update_head.GetPosition()];
+
+      int new_pos = m_promoter_update_head.GetPosition();
+      new_pos += inc;
+      if ( new_pos >= genome_size )
+      {
+        new_pos++;
+        new_pos %= inc;
+      }
+      
+      assert((new_pos >= 0) && (new_pos < genome_size));
+      m_promoter_update_head.Set(new_pos);
+    }
+    m_promoter_states[m_promoter_update_head.GetPosition()] -= 1.0;
+    
+    // Create new programid
+    cGenome new_genome(m_world->GetConfig().IMPLICIT_MAX_PROGRAMID_LENGTH.Get());
+    programid_ptr new_programid = new cProgramid(new_genome, this);
+    new_programid->SetExecutable(true);
+    AddProgramid(new_programid);
+    
+    cHeadProgramid read_head(m_promoter_update_head);
+    read_head++; //Don't copy the promoter instruction itself
+    cHeadProgramid write_head(this, 0, new_programid->GetID());
+    int copied = 0;
+    cInstruction inst;
+    do {
+      inst = read_head.GetInst();
+      if (inst == terminator_inst) break; // Early termination 
+      write_head.SetInst(inst);
+      write_head++;
+      read_head++;
+      copied++;
+    } while (write_head.GetPosition() != 0);
+
+    // Set the read head of this programid to where it began so that we can keep track in trace files.
+    new_programid->GetHead(nHardware::HEAD_READ).Set(m_promoter_update_head.GetPosition(),0);
+    // Adjust length downward if prematurely terminated...
+    if (inst == terminator_inst)
+    {
+      new_programid->m_memory.ResizeOld( Max(1, copied) );
+      // If the length was zero, then we are left with a single NOP.
+    }
+    
+    if (m_world->GetVerbosity() >= VERBOSE_DETAILS)
+    {
+      cout << "New programid created. Start position = " << new_programid->GetHead(nHardware::HEAD_READ).GetPosition();
+      cout << " length = " <<  new_programid->m_memory.GetSize() << endl;
+    }
+  }
+
+  m_promoter_update_head++;
+  
+}
+
 /*! Construct this cProgramid, and initialize hardware resources.
 */
 cHardwareGX::cProgramid::cProgramid(const cGenome& genome, cHardwareGX* hardware)
-: m_memory(genome)
+: m_gx_hardware(hardware)
+, m_unique_id(hardware->m_last_unique_id_assigned++)
 , m_executable(false)
 , m_bindable(false)
 , m_readable(false)
+, m_marked_for_death(false)
+, m_cpu_cycles_used(0)
 , m_copying_site(false)
-, m_cpu_cycles_used(0)
-, m_gx_hardware(hardware)
-, m_unique_id(hardware->m_last_unique_id_assigned++)
-, m_inputBuffer(m_gx_hardware->m_world->GetEnvironment().GetInputSize())
-, m_outputBuffer(m_gx_hardware->m_world->GetEnvironment().GetOutputSize())
+, m_memory(genome)
+, m_input_buf(m_gx_hardware->m_world->GetEnvironment().GetInputSize())
+, m_output_buf(m_gx_hardware->m_world->GetEnvironment().GetOutputSize())
 {
   assert(m_gx_hardware!=0);
   for(int i=0; i<NUM_HEADS; ++i) {
     m_heads[i].Reset(hardware);
   }
 
-  // Check what flags should be set on this programid.
-  for(int i=0; i<m_memory.GetSize();) {
-    if(m_memory[i]==GetInst("PROGRAMID")) { 
-      m_memory.Remove(i);
-      continue;
+  if (!m_gx_hardware->m_world->GetConfig().IMPLICIT_GENE_EXPRESSION.Get())
+  {
+    // Check what flags should be set on this programid.
+    for(int i=0; i<m_memory.GetSize();) {
+      if(m_memory[i]==GetInst("PROGRAMID")) { 
+        m_memory.Remove(i);
+        continue;
+      }
+      if(m_memory[i]==GetInst("EXECUTABLE")) { 
+        m_memory.Remove(i); 
+        m_executable=true;
+        continue;
+      }
+      if(m_memory[i]==GetInst("BINDABLE")) { 
+        m_memory.Remove(i);
+        m_bindable=true;
+        continue;
+      }
+      if(m_memory[i]==GetInst("READABLE")) { 
+        m_memory.Remove(i);
+        m_readable=true;
+        continue;
+      }
+      ++i;
     }
-    if(m_memory[i]==GetInst("EXECUTABLE")) { 
-      m_memory.Remove(i); 
-      m_executable=true;
-      continue;
-    }
-    if(m_memory[i]==GetInst("BINDABLE")) { 
-      m_memory.Remove(i);
-      m_bindable=true;
-      continue;
-    }
-    if(m_memory[i]==GetInst("READABLE")) { 
-      m_memory.Remove(i);
-      m_readable=true;
-      continue;
-    }
-    ++i;
   }
+  
+  Reset();
 }
 
+void cHardwareGX::cProgramid::ResetHeads() 
+{
+  for(int i=0; i<NUM_HEADS; ++i) {
+    m_heads[i].SetProgramid(this);
+    m_heads[i].Reset(m_gx_hardware, m_id);
+  }
+}
 
+void cHardwareGX::cProgramid::Reset()
+{  
+  for (int i = 0; i < NUM_REGISTERS; i++) m_regs[i] = 0;
+  ResetHeads();
+  
+  m_stack.Clear();
+  m_read_label.Clear();
+  m_next_label.Clear();
+}
+
 /*! Append this programid's genome to the passed in genome.  Include the tags
 that specify what this programid is capable of.
 */
@@ -3983,6 +4331,7 @@
     search_head++;
   } while ( search_head.GetPosition() != first_non_nop ); // back at the beginning 
 
+  return matches;
 }
 
 

Modified: development/source/cpu/cHardwareGX.h
===================================================================
--- development/source/cpu/cHardwareGX.h	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/source/cpu/cHardwareGX.h	2007-06-22 20:19:35 UTC (rev 1708)
@@ -68,13 +68,6 @@
 class cMutation;
 class cOrganism;
 
-/* The big TODO list
-
-1. Create a cGXOrganism class and remove all of the psudo-genome nonsense.
-   This will fix the artifact that programid ages get reset in the daughter.
-
-*/
-
 /*! Each organism may have a cHardwareGX structure that keeps track of the 
 * current status of simulated hardware.  This particular CPU architecture is
 * designed to explore the evolution of gene expression and also the effect
@@ -89,20 +82,20 @@
   //! Number of heads each cProgramid has.
   static const int NUM_HEADS = nHardware::NUM_HEADS >= NUM_REGISTERS ? nHardware::NUM_HEADS : NUM_REGISTERS;
   static const int NUM_NOPS = 3; //!< Number of NOPS that cHardwareGX supports.
+    
+  // GX "options" that haven't graduated to the Config File
+  
+  // "Normal" Model
 
-  //!< \todo JEB Make these config options
-  static const unsigned int MAX_PROGRAMIDS = 32; //!< Number of cProgramids that an organism can allocate.
-  static const int MAX_PROGRAMID_TOTAL_LENGTH = 1000; // New programids cannot be created if above this cumulative length.
   static const int PROGRAMID_REPLACEMENT_METHOD = 0;
    //!< Controls what happens when we try to allocate a new cProgramid, but are up against the limit
-  // 0 = Fail if no programids available
-  // 1 = Replace the programid that has completed the most instructions
-  static const int MAX_PROGRAMID_AGE = 2000; // Number of inst a cProgramid executes before ceasing to exist
-  static const double EXECUTABLE_COPY_PROCESSIVITY;
-  static const double READABLE_COPY_PROCESSIVITY;
+    // 0 = Fail if no programids available
+    // 1 = Replace the programid that has used the most cpu cycles
+  static const double EXECUTABLE_COPY_PROCESSIVITY; // Set to 1.0 by default
+  static const double READABLE_COPY_PROCESSIVITY;   // Set to 1.0 by default
+  
+  unsigned int m_last_unique_id_assigned; // Counter: so programids can be assigned unique IDs for tracking
 
-  unsigned int m_last_unique_id_assigned; // Counter so programids can be assigned unique IDs for tracking
-
   //! Enums for the different supported registers.
   enum tRegisters { REG_AX=0, REG_BX, REG_CX };
   
@@ -126,7 +119,7 @@
   private:
     cProgramid* m_programid;
   public:
-    cHeadProgramid() : cHeadCPU(), m_programid(NULL) {  }
+    cHeadProgramid(cHardwareBase* hw = NULL, int pos = 0, int ms = 0) : cHeadCPU(hw, pos, ms) , m_programid(NULL) {  };
     ~cHeadProgramid() { ; }
       
     void SetProgramid(cProgramid* _programid) { m_programid = _programid; }
@@ -148,6 +141,8 @@
   public:
     //! Constructs a cProgramid from a genome and CPU.
     cProgramid(const cGenome& genome, cHardwareGX* hardware);
+    ~cProgramid() {}
+    
     //! Returns whether and where this cProgramid matches the passed-in label.
     std::vector<cHardwareGX::cMatchSite> Sites(const cCodeLabel& label);
     //! Binds one of this cProgramid's heads to the passed-in match site.
@@ -170,12 +165,8 @@
       m_contacting_heads++; 
     }
     
-    void ResetHeads() {
-      for(int i=0; i<NUM_HEADS; ++i) {
-        m_heads[i].SetProgramid(this);
-        m_heads[i].Reset(m_gx_hardware, m_id);
-      }
-    }
+    void ResetHeads();    
+    void Reset();
     
     // Accessors
     bool GetExecute() { return m_executable && (m_contacting_heads == 0); }
@@ -183,6 +174,8 @@
     bool GetBindable() { return m_bindable; }
     bool GetReadable() { return m_readable; }
     int  GetID() { return m_id; }
+    tBuffer<int>& GetInputBuf() { return m_input_buf; }
+    tBuffer<int>& GetOutputBuf() { return m_output_buf; }
     int  GetCPUCyclesUsed() { return m_cpu_cycles_used; }
     void ResetCPUCyclesUsed() { m_cpu_cycles_used = 0; }
     cInstruction GetInst(cString inst) { assert(m_gx_hardware); return m_gx_hardware->GetInstSet().GetInst(inst); }
@@ -214,6 +207,7 @@
     bool m_executable;  //!< Is this programid ever executable? Currently, a programid with head from another cProgramid on it is also stopped. 
     bool m_bindable; //!< Is this programid bindable, i.e. can other programids put their read heads on it?
     bool m_readable; //!< Is this programid readable?
+    bool m_marked_for_death; //!< Is this programid marked for deletion?
     int m_cpu_cycles_used; //!< Number of cpu cycles this programid has used.
 
     bool m_copying_site; //! Are we in the middle of copying a "site" (which could cause termination)
@@ -221,15 +215,17 @@
     cCodeLabel m_terminator_label; //!< The label that this cProgramid must traverse to disassociate.
 
     // Core variables maintained from previous incarnation as a thread
-    cCodeLabel m_readLabel; //!< ?
-    cCodeLabel m_nextLabel; //!< ?
+    cCodeLabel m_read_label; //!< ?
+    cCodeLabel m_next_label; //!< ?
     cCPUMemory m_memory; //!< This cProgramid's genome fragment.
     cCPUStack m_stack; //!< This cProgramid's stack (no global stack).
     cHeadProgramid m_heads[NUM_HEADS]; //!< This cProgramid's heads.
     int m_regs[NUM_REGISTERS]; //!< This cProgramid's registers.
     
-    tBuffer<int> m_inputBuffer; //!< This programid's input buffer.
-    tBuffer<int> m_outputBuffer; //!< This programid's output buffer.
+    int m_input_pointer;
+    tBuffer<int> m_input_buf; //!< This programid's input buffer.
+    tBuffer<int> m_output_buf; //!< This programid's output buffer.
+
   };
   
 protected:
@@ -239,6 +235,13 @@
   programid_list m_programids; //!< The list of cProgramids.
   programid_ptr m_current; //!< The currently-executing cProgramid.
   
+  // Implicit RNAP Model only
+  cHeadProgramid m_promoter_update_head; //Promoter position that last executable programid was created from.
+  tArray<double> m_promoter_states;
+  tArray<double> m_promoter_rates;
+  double m_recycle_state;
+  double m_promoter_sum;
+  
   // --------  Member Variables  --------
   const tMethod* m_functions;
 
@@ -271,15 +274,15 @@
   void AdjustHeads();
   
   // --------  Label Manipulation  -------
-  const cCodeLabel& GetLabel() const { assert(m_current); return m_current->m_nextLabel; }
-  cCodeLabel& GetLabel() { assert(m_current); return m_current->m_nextLabel; }
+  const cCodeLabel& GetLabel() const { assert(m_current); return m_current->m_next_label; }
+  cCodeLabel& GetLabel() { assert(m_current); return m_current->m_next_label; }
   void ReadLabel(int max_size=nHardware::MAX_LABEL_SIZE);
   cHeadCPU FindLabel(int direction);
   int FindLabel_Forward(const cCodeLabel & search_label, const cGenome& search_genome, int pos);
   int FindLabel_Backward(const cCodeLabel & search_label, const cGenome& search_genome, int pos);
   cHeadCPU FindLabel(const cCodeLabel & in_label, int direction);
-  const cCodeLabel& GetReadLabel() const { assert(m_current); return m_current->m_readLabel; }
-  cCodeLabel& GetReadLabel() { assert(m_current); return m_current->m_readLabel; }
+  const cCodeLabel& GetReadLabel() const { assert(m_current); return m_current->m_read_label; }
+  cCodeLabel& GetReadLabel() { assert(m_current); return m_current->m_read_label; }
 
   // ---------- Instruction Helpers -----------
   int FindModifiedRegister(int default_register);
@@ -293,6 +296,7 @@
   bool Allocate_Default(const int new_size);
   bool Allocate_Main(cAvidaContext& ctx, const int allocated_size);
   
+  int GetExecutedSize(const int parent_size);
   int GetCopiedSize(const int parent_size, const int child_size);
   bool Divide_Main(cAvidaContext& ctx);
   void InjectCode(const cGenome& injection, const int line_num);
@@ -300,7 +304,7 @@
   void ReadInst(const int in_inst);
 
 public:
-  //! Main constructor for cHardwareGX; called from cHardwareManager for every(?) organism.
+  //! Main constructor for cHardwareGX; called from cHardwareManager for every organism.
   cHardwareGX(cWorld* world, cOrganism* in_organism, cInstSet* in_inst_set);
   virtual ~cHardwareGX(); //!< Destructor; removes all cProgramids.
     
@@ -317,7 +321,6 @@
   bool OK();
   void PrintStatus(std::ostream& fp);
 
-
   // --------  Stack Manipulation...  --------
   inline int GetStack(int depth=0, int stack_id=-1, int in_thread=-1) const { assert(m_current); return m_current->m_stack.Get(depth); }
   inline int GetNumStacks() const { return 2; }
@@ -363,9 +366,14 @@
   virtual int GetNumThreads() const { return -1; }
   virtual int GetCurThread() const { return -1; }
   virtual int GetCurThreadID() const { return -1; }
-  
+ 
+   // --------  Parasite Stuff  --------
   bool InjectHost(const cCodeLabel& in_label, const cGenome& injection);
-  
+
+  // --------  Input/Output Buffers  --------
+  virtual tBuffer<int>& GetInputBuf() { return m_current->GetInputBuf(); }
+  virtual tBuffer<int>& GetOutputBuf() { return m_current->GetOutputBuf(); }
+
 private:
   cHardwareGX& operator=(const cHardwareGX&); //!< Not implemented.
   cHardwareGX(const cHardwareGX&); //!< Not implemented.
@@ -479,6 +487,8 @@
   bool Inst_MaxAlloc(cAvidaContext& ctx);
   bool Inst_Inject(cAvidaContext& ctx);
   bool Inst_InjectRand(cAvidaContext& ctx);
+  
+  bool Inst_Repro(cAvidaContext& ctx);
 
   bool Inst_SpawnDeme(cAvidaContext& ctx);
   bool Inst_Kazi(cAvidaContext& ctx);
@@ -567,12 +577,21 @@
   bool Inst_NumSites(cAvidaContext& ctx); //!< Count the number of corresponding binding sites
   bool Inst_ProgramidCopy(cAvidaContext& ctx); //!< Like h-copy, but fails if read/write heads not on other programids and will not write over
   bool Inst_ProgramidDivide(cAvidaContext& ctx); //!< Like h-divide, 
-  bool Inst_ProgramidGet(cAvidaContext& ctx); //!< Like get with head resets.
-  bool Inst_ProgramidPut(cAvidaContext& ctx); //!< Like put with head and input resets.
+  bool Inst_ProgramidImplicitAllocate(cAvidaContext& ctx);
+  bool Inst_ProgramidImplicitDivide(cAvidaContext& ctx);
+  bool Inst_EndProgramidExecution(cAvidaContext& ctx);
   
+  bool Inst_Promoter(cAvidaContext& ctx);
+  bool Inst_Terminator(cAvidaContext& ctx);
+  bool Inst_HeadRegulate(cAvidaContext& ctx);
+
   //!< Add/Remove a new programid to/from the list and give it the proper index within the list so we keep track of memory spaces...
   void AddProgramid(programid_ptr programid);
-  void RemoveProgramid(unsigned int remove_index);  
+  void RemoveProgramid(unsigned int remove_index);
+  
+  // Create executable programids in the implicit GX model
+  void ProcessImplicitGeneExpression(int in_limit = -1);  
+  
 };
 
 

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/source/main/cAvidaConfig.h	2007-06-22 20:19:35 UTC (rev 1708)
@@ -206,8 +206,6 @@
   CONFIG_ADD_VAR(ENVIRONMENT_FILE, cString, "environment.cfg", "File that describes the environment");
   CONFIG_ADD_VAR(START_CREATURE, cString, "default-classic.org", "Organism to seed the soup");
   
-  
-  // Deme & germline group.
   CONFIG_ADD_GROUP(DEME_GROUP, "Demes and Germlines");
   CONFIG_ADD_VAR(NUM_DEMES, int, 1, "Number of independent groups in the population.");
   CONFIG_ADD_VAR(DEMES_USE_GERMLINE, int, 0, "Whether demes use a distinct germline; 0=off");
@@ -217,7 +215,6 @@
   CONFIG_ADD_VAR(GERMLINE_RANDOM_PLACEMENT, int, 0, "Whether the seed for a germline is placed\n randomly within the deme; 0=no.");
   CONFIG_ADD_VAR(MAX_DEME_AGE, int, 500, "The maximum age of a deme (in updates) to be\nused for age-based replication (default=500).");  
   
-  
   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");
   CONFIG_ADD_VAR(PREFER_EMPTY, int, 1, "Give empty cells preference in offsping placement?");
@@ -303,14 +300,6 @@
   CONFIG_ADD_VAR(DONATE_THRESH_QUANTA, int, 10, "The size of steps between quanta donate thresholds");
   CONFIG_ADD_VAR(MAX_DONATES, int, 1000000, "Limit on number of donates organisms are allowed.");
   CONFIG_ADD_VAR(PRECALC_MERIT, int, 0, "Pre-calculate merit at birth (unlimited resources only).");
-	
-  CONFIG_ADD_GROUP(PROMOTER_GROUP, "Promoters");
-  CONFIG_ADD_VAR(PROMOTERS_ENABLED, int, 0, "Use the promoter/terminator execution scheme.\nCertain instructions must also be included.");
-  CONFIG_ADD_VAR(PROMOTER_PROCESSIVITY, double, 1.0, "Chance of not terminating after each cpu cycle.");
-  CONFIG_ADD_VAR(PROMOTER_PROCESSIVITY_INST, double, 1.0, "Chance of not terminating after each instruction.");
-  CONFIG_ADD_VAR(PROMOTER_BG_STRENGTH, double, 0, "Probability of positions that are not promoter\ninstructions initiating execution (promoters are 1).");
-  CONFIG_ADD_VAR(REGULATION_STRENGTH, double, 1, "Strength added or subtracted to a promoter by regulation.");
-  CONFIG_ADD_VAR(REGULATION_DECAY_FRAC, double, 0.1, "Fraction of regulation that decays away. \nMax regulation = 2^(REGULATION_STRENGTH/REGULATION_DECAY_FRAC)");
 
   CONFIG_ADD_GROUP(GENEOLOGY_GROUP, "Geneology");
   CONFIG_ADD_VAR(TRACK_MAIN_LINEAGE, int, 1, "Keep all ancestors of the active population?\n0=no, 1=yes, 2=yes,w/sexual population");
@@ -356,7 +345,7 @@
   CONFIG_ADD_VAR(FRAC_PARENT_ENERGY_GIVEN_AT_BIRTH, double, 0.5, "Fraction of perent's energy given to offspring.");
   CONFIG_ADD_VAR(FRAC_ENERGY_DECAY_AT_BIRTH, double, 0.0, "Fraction of energy lost due to decay during reproduction.");
   CONFIG_ADD_VAR(NUM_INST_EXC_BEFORE_0_ENERGY, int, 0, "Number of instructions executed before energy is exhausted.");
-  CONFIG_ADD_VAR(ENERGY_CAP, int, -1, "Maximun amount of energy that can be stored in an organism.  -1 means the cap is set to Max Int");  // TODO - is this done?
+  CONFIG_ADD_VAR(ENERGY_CAP, int, -1, "Maximum amount of energy that can be stored in an organism.  -1 means the cap is set to Max Int");  // TODO - is this done?
   CONFIG_ADD_VAR(APPLY_ENERGY_METHOD, int, 0, "When should rewarded energy be applied to current energy?\n0 = on divide\n1 = on completion of task\n2 = on sleep");  
   CONFIG_ADD_VAR(ENERGY_VERBOSE, bool, 0, "Print energy and merit values. 0/1 (off/on)");
   CONFIG_ADD_VAR(LOG_SLEEP_TIMES, bool, 0, "Log sleep start and end times. 0/1 (off/on)\nWARNING: may use lots of memory.");
@@ -365,6 +354,27 @@
   CONFIG_ADD_GROUP(SECOND_PASS_GROUP, "Tracking metrics known after the running experiment previously");
   CONFIG_ADD_VAR(TRACK_CCLADES, int, 0, "Enable tracking of coalescence clades");
   CONFIG_ADD_VAR(TRACK_CCLADES_IDS, cString, "coalescence.ids", "File storing coalescence IDs");
+  
+  CONFIG_ADD_GROUP(GX_GROUP, "Gene Expression CPU Settings");
+  CONFIG_ADD_VAR(MAX_PROGRAMIDS, int, 16, "Maximum number of programids an organism can create.");
+  CONFIG_ADD_VAR(MAX_PROGRAMID_AGE, int, 2000, "Max number of CPU cycles a programid executes before it is removed.");
+  CONFIG_ADD_VAR(IMPLICIT_GENE_EXPRESSION, int, 0, "Create executable programids from the genome without explicit allocation and copying?");
+  CONFIG_ADD_VAR(IMPLICIT_BG_PROMOTER_RATE, double, 0.0, "Relative rate of non-promoter sites creating programids.");
+  CONFIG_ADD_VAR(IMPLICIT_TURNOVER_RATE, double, 0.0, "Number of programids recycled per CPU cycle. 0 = OFF");
+  CONFIG_ADD_VAR(IMPLICIT_MAX_PROGRAMID_LENGTH, int, 0, "Creation of an executable programid terminates after this many instructions. 0 = disabled");
+  CONFIG_ADD_VAR(IMPLICIT_REPRO_TIME, int, 0, "Implicitly call the repro instruction after completing this many cpu cycles. 0 = disabled."); // TODO - implmement for all hardware types and move to Reproduction Group 
+  CONFIG_ADD_VAR(DIVIDE_SLIP_PROB, double, 0.0, ""); // TODO - implmement for all hardware types and move to Reproduction Group 
+
+//  CONFIG_ADD_VAR(CLEAR_ON_OUTPUT, int, 0, "Reset input buffer every time output called?"); @JEB Not fully implemented
+
+  CONFIG_ADD_GROUP(PROMOTER_GROUP, "Promoters");
+  CONFIG_ADD_VAR(PROMOTERS_ENABLED, int, 0, "Use the promoter/terminator execution scheme.\nCertain instructions must also be included.");
+  CONFIG_ADD_VAR(PROMOTER_PROCESSIVITY, double, 1.0, "Chance of not terminating after each cpu cycle.");
+  CONFIG_ADD_VAR(PROMOTER_PROCESSIVITY_INST, double, 1.0, "Chance of not terminating after each instruction.");
+  CONFIG_ADD_VAR(PROMOTER_BG_STRENGTH, double, 0, "Probability of positions that are not promoter\ninstructions initiating execution (promoters are 1).");
+  CONFIG_ADD_VAR(REGULATION_STRENGTH, double, 1, "Strength added or subtracted to a promoter by regulation.");
+  CONFIG_ADD_VAR(REGULATION_DECAY_FRAC, double, 0.1, "Fraction of regulation that decays away. \nMax regulation = 2^(REGULATION_STRENGTH/REGULATION_DECAY_FRAC)");
+
 #endif
   
   void Load(const cString& filename, const bool& crash_if_not_found);

Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/source/main/cOrganism.cc	2007-06-22 20:19:35 UTC (rev 1708)
@@ -218,7 +218,6 @@
   
   tArray<double> res_change(resource_count.GetSize());
   tArray<int> insts_triggered;
-  bool clear_input = false;
   
   tBuffer<int>* received_messages_point = &m_received_messages;
   if (!m_world->GetConfig().SAVE_RECEIVED.Get()) received_messages_point = NULL;
@@ -236,13 +235,14 @@
   }
 
   m_interface->UpdateResources(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));
   }
   
-  if(clear_input) input_buffer.Clear();  
 }
 
 
@@ -481,11 +481,11 @@
   fp << endl;
   
   fp << "Input (buf):";
-  for (int i = 0; i < m_input_buf.GetNumStored(); i++) fp << " 0x" << setw(8) << m_input_buf[i];
+  for (int i = 0; i < m_hardware->GetInputBuf().GetNumStored(); i++) fp << " 0x" << setw(8) << m_hardware->GetInputBuf()[i];
   fp << endl;
 
   fp << "Output:     ";
-  for (int i = 0; i < m_output_buf.GetNumStored(); i++) fp << " 0x" << setw(8) << m_output_buf[i];
+  for (int i = 0; i < m_hardware->GetOutputBuf().GetNumStored(); i++) fp << " 0x" << setw(8) << m_hardware->GetOutputBuf()[i];
   fp << endl;
   
   fp << setfill(' ') << setbase(10);

Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/source/main/cOrganism.h	2007-06-22 20:19:35 UTC (rev 1708)
@@ -84,7 +84,7 @@
 {
 protected:
   cWorld* m_world;
-  cHardwareBase* m_hardware;              // The actual machinary running this organism.
+  cHardwareBase* m_hardware;              // The actual machinery running this organism.
   cGenotype* m_genotype;                  // Information about organisms with this genome.
   cPhenotype m_phenotype;                 // Descriptive attributes of organism.
   const cGenome m_initial_genome;         // Initial genome; can never be changed!
@@ -185,6 +185,9 @@
   void Rotate(int direction) { m_interface->Rotate(direction); }
   void DoBreakpoint() { m_interface->Breakpoint(); }
   int GetNextInput() { return m_interface->GetInputAt(m_input_pointer); }
+  int GetNextInput(int& in_input_pointer) { return m_interface->GetInputAt(in_input_pointer); } //@JEB alternate for GX
+  tBuffer<int>& GetInputBuf() { return m_input_buf; }
+  tBuffer<int>& GetOutputBuf() { return m_output_buf; }
   void Die() { m_interface->Die(); }
   void Kaboom(int dist) { m_interface->Kaboom(dist);}
   void SpawnDeme() { m_interface->SpawnDeme(); }

Modified: development/support/config/avida.cfg
===================================================================
--- development/support/config/avida.cfg	2007-06-21 18:58:44 UTC (rev 1707)
+++ development/support/config/avida.cfg	2007-06-22 20:19:35 UTC (rev 1708)
@@ -194,19 +194,8 @@
                             # donation attempt threshold; -1=no thresh
 DONATE_THRESH_QUANTA 10     # The size of steps between quanta donate thresholds
 MAX_DONATES 1000000         # Limit on number of donates organisms are allowed.
+PRECALC_MERIT 0             # Pre-calculate merit at birth (unlimited resources only).
 
-### PROMOTER_GROUP ###
-# Promoters
-PROMOTERS_ENABLED 0             # Use the promoter/terminator execution scheme.
-                                # Certain instructions must also be included.
-PROMOTER_PROCESSIVITY 1.0       # Chance of not terminating after each cpu cycle.
-PROMOTER_PROCESSIVITY_INST 1.0  # Chance of not terminating after each instruction.
-PROMOTER_BG_STRENGTH 0          # Probability of positions that are not promoter
-                                # instructions initiating execution (promoters are 1).
-REGULATION_STRENGTH 1           # Strength added or subtracted to a promoter by regulation.
-REGULATION_DECAY_FRAC 0.1       # Fraction of regulation that decays away. 
-                                # Max regulation = 2^(REGULATION_STRENGTH/REGULATION_DECAY_FRAC)
-
 ### GENEOLOGY_GROUP ###
 # Geneology
 TRACK_MAIN_LINEAGE 1  # Keep all ancestors of the active population?
@@ -271,7 +260,47 @@
 ANALYZE_OPTION_1   # String variable accessible from analysis scripts
 ANALYZE_OPTION_2   # String variable accessible from analysis scripts
 
+### ENERGY_GROUP ###
+# Energy Settings
+ENERGY_ENABLED 0                       # Enable Energy Model. 0/1 (off/on)
+ENERGY_GIVEN_ON_INJECT 0               # Energy given to organism upon injection.
+ENERGY_GIVEN_AT_BIRTH 0                # Energy given to offspring upon birth.
+FRAC_PARENT_ENERGY_GIVEN_AT_BIRTH 0.5  # Fraction of perent's energy given to offspring.
+FRAC_ENERGY_DECAY_AT_BIRTH 0.0         # Fraction of energy lost due to decay during reproduction.
+NUM_INST_EXC_BEFORE_0_ENERGY 0         # Number of instructions executed before energy is exhausted.
+ENERGY_CAP -1                          # Maximum amount of energy that can be stored in an organism.  -1 means the cap is set to Max Int
+APPLY_ENERGY_METHOD 0                  # When should rewarded energy be applied to current energy?
+                                       # 0 = on divide
+                                       # 1 = on completion of task
+                                       # 2 = on sleep
+ENERGY_VERBOSE 0                       # Print energy and merit values. 0/1 (off/on)
+LOG_SLEEP_TIMES 0                      # Log sleep start and end times. 0/1 (off/on)
+                                       # WARNING: may use lots of memory.
+
 ### SECOND_PASS_GROUP ###
 # Tracking metrics known after the running experiment previously
 TRACK_CCLADES 0                    # Enable tracking of coalescence clades
 TRACK_CCLADES_IDS coalescence.ids  # File storing coalescence IDs
+
+### GX_GROUP ###
+# Gene Expression CPU Settings
+MAX_PROGRAMIDS 16                # Maximum number of programids an organism can create.
+MAX_PROGRAMID_AGE 2000           # Max number of CPU cycles a programid executes before it is removed.
+IMPLICIT_GENE_EXPRESSION 0       # Create executable programids from the genome without explicit allocation and copying?
+IMPLICIT_BG_PROMOTER_RATE 0.0    # Relative rate of non-promoter sites creating programids.
+IMPLICIT_TURNOVER_RATE 0.0       # Number of programids recycled per CPU cycle. 0 = OFF
+IMPLICIT_MAX_PROGRAMID_LENGTH 0  # Creation of an executable programid terminates after this many instructions. 0 = disabled
+IMPLICIT_REPRO_TIME 0            # Implicitly call the repro instruction after completing this many cpu cycles. 0 = disabled.
+DIVIDE_SLIP_PROB 0.0             # 
+
+### PROMOTER_GROUP ###
+# Promoters
+PROMOTERS_ENABLED 0             # Use the promoter/terminator execution scheme.
+                                # Certain instructions must also be included.
+PROMOTER_PROCESSIVITY 1.0       # Chance of not terminating after each cpu cycle.
+PROMOTER_PROCESSIVITY_INST 1.0  # Chance of not terminating after each instruction.
+PROMOTER_BG_STRENGTH 0          # Probability of positions that are not promoter
+                                # instructions initiating execution (promoters are 1).
+REGULATION_STRENGTH 1           # Strength added or subtracted to a promoter by regulation.
+REGULATION_DECAY_FRAC 0.1       # Fraction of regulation that decays away. 
+                                # Max regulation = 2^(REGULATION_STRENGTH/REGULATION_DECAY_FRAC)




More information about the Avida-cvs mailing list