[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