[Avida-SVN] r1149 - in development: Avida.xcodeproj source/analyze source/cpu source/main source/tools

brysonda at myxo.css.msu.edu brysonda at myxo.css.msu.edu
Tue Dec 19 13:11:08 PST 2006


Author: brysonda
Date: 2006-12-19 16:11:08 -0500 (Tue, 19 Dec 2006)
New Revision: 1149

Modified:
   development/Avida.xcodeproj/project.pbxproj
   development/source/analyze/cAnalyze.cc
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cTestCPU.cc
   development/source/main/cEnvironment.cc
   development/source/main/cEnvironment.h
   development/source/main/cOrganism.cc
   development/source/main/cTaskContext.h
   development/source/main/cTaskLib.cc
   development/source/main/cTaskLib.h
   development/source/tools/tHashTable.h
Log:
Implement sort_inputs task.  This task requires that the size (how many numbers to sort) and halflife (decay of quality for each out of place element) arguments be specified.  Additionally the direction (ascending vs. descending sort) and contiguous options can be set.

Adjust cTestCPU environment input setup to support input size variation.  Specifically moved static input support into cEnvironment.

Move task quality calculation after requisite testing.  This allows on_divide task calculations to be skipped during normal task evaluation.

Enhance hardware tracing to print IO status (input from the environment, the input buffer, and the output buffer).  Also print out the full stacks in cHardwareCPU, as well as the current selected stack (denoted as an asterisk before the stack line).

Modified: development/Avida.xcodeproj/project.pbxproj
===================================================================
--- development/Avida.xcodeproj/project.pbxproj	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/Avida.xcodeproj/project.pbxproj	2006-12-19 21:11:08 UTC (rev 1149)
@@ -8,7 +8,6 @@
 
 /* Begin PBXBuildFile section */
 		1097463F0AE9606E00929ED6 /* cDeme.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1097463D0AE9606E00929ED6 /* cDeme.cc */; };
-		109746400AE9606E00929ED6 /* cDeme.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1097463E0AE9606E00929ED6 /* cDeme.h */; };
 		109746410AE9606E00929ED6 /* cDeme.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1097463D0AE9606E00929ED6 /* cDeme.cc */; };
 		109746420AE9606E00929ED6 /* cDeme.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1097463E0AE9606E00929ED6 /* cDeme.h */; };
 		109746430AE9606E00929ED6 /* cDeme.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1097463D0AE9606E00929ED6 /* cDeme.cc */; };
@@ -111,7 +110,6 @@
 		708BF3000AB65DC700A923BF /* cEventList.cc in Sources */ = {isa = PBXBuildFile; fileRef = 708BF2FD0AB65DC700A923BF /* cEventList.cc */; };
 		7099EEC00B2F9D2A001269F6 /* cEnvReqs.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7099EEBF0B2F9D2A001269F6 /* cEnvReqs.h */; };
 		7099EEC10B2F9D2A001269F6 /* cEnvReqs.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7099EEBF0B2F9D2A001269F6 /* cEnvReqs.h */; };
-		7099EEC20B2F9D2A001269F6 /* cEnvReqs.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7099EEBF0B2F9D2A001269F6 /* cEnvReqs.h */; };
 		7099EF510B2FBC85001269F6 /* cAnalyzeScreen.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7099EF470B2FBC85001269F6 /* cAnalyzeScreen.cc */; };
 		7099EF530B2FBC85001269F6 /* cAnalyzeView.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7099EF490B2FBC85001269F6 /* cAnalyzeView.cc */; };
 		7099EF560B2FBC86001269F6 /* cTextViewerAnalyzeDriver.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7099EF4C0B2FBC85001269F6 /* cTextViewerAnalyzeDriver.cc */; };
@@ -432,8 +430,6 @@
 				7049F3710A66AD7E00640512 /* default-sex-classic.org in CopyFiles */,
 				7049F3720A66AD7E00640512 /* default-smt.org in CopyFiles */,
 				7049F3730A66AD7E00640512 /* default-transsmt.org in CopyFiles */,
-				109746400AE9606E00929ED6 /* cDeme.h in CopyFiles */,
-				7099EEC20B2F9D2A001269F6 /* cEnvReqs.h in CopyFiles */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: development/source/analyze/cAnalyze.cc
===================================================================
--- development/source/analyze/cAnalyze.cc	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/analyze/cAnalyze.cc	2006-12-19 21:11:08 UTC (rev 1149)
@@ -1696,9 +1696,9 @@
     test_info.SetTraceExecution(&trace_printer);
     test_info.UseRandomInputs(useRandomInputs==1); 
     
+    if (m_world->GetVerbosity() >= VERBOSE_ON) cout << "  Tracing: " << filename << endl;
     testcpu->TestGenome(m_ctx, test_info, genotype->GetGenome());
     
-    if (m_world->GetVerbosity() >= VERBOSE_ON) cout << "  Tracing: " << filename << endl;
     m_world->GetDataFileManager().Remove(filename);
   }
   

Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/cpu/cHardwareCPU.cc	2006-12-19 21:11:08 UTC (rev 1149)
@@ -650,8 +650,9 @@
     
   int number_of_stacks = GetNumStacks();
   for (int stack_id = 0; stack_id < number_of_stacks; stack_id++) {
-    fp << "Top of stack " << stack_id << ":"
-    << GetStack(0, stack_id, 0) << endl;
+    fp << ((m_threads[m_cur_thread].cur_stack == stack_id) ? '*' : ' ') << " Stack " << stack_id << ":" << setbase(16) << setfill('0');
+    for (int i = 0; i < nHardware::STACK_SIZE; i++) fp << " Ox" << setw(8) << GetStack(i, stack_id, 0);
+    fp << setfill(' ') << setbase(10) << endl;
   }
   
   fp << "  Mem (" << GetMemory().GetSize() << "):"

Modified: development/source/cpu/cTestCPU.cc
===================================================================
--- development/source/cpu/cTestCPU.cc	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/cpu/cTestCPU.cc	2006-12-19 21:11:08 UTC (rev 1149)
@@ -208,27 +208,20 @@
 {
   assert(cur_depth < test_info.generation_tests);
 
-  if (test_info.GetUseRandomInputs() == false) {
-    // We make sure that all combinations of inputs are present.  This is
-    // done explicitly in the key columns... (0f, 33, and 55)
-    input_array.Resize(3);
-    //    input_array[0] = 0x130f149f;  // 00010011 00001111 00010100 10011111
-    //    input_array[1] = 0x0833e53e;  // 00001000 00110011 11100101 00111110
-    //    input_array[2] = 0x625541eb;  // 01100010 01010101 01000001 11101011
+  // Input sizes can vary based on environment settings, must at least initialize
+  m_world->GetEnvironment().SetupInputs(ctx, input_array, test_info.GetUseRandomInputs());
 
-    input_array[0] = 0x0f13149f;  // 00001111 00010011 00010100 10011111
-    input_array[1] = 0x3308e53e;  // 00110011 00001000 11100101 00111110
-    input_array[2] = 0x556241eb;  // 01010101 01100010 01000001 11101011
-
-    receive_array.Resize(3);
+  receive_array.Resize(3);
+  if (test_info.GetUseRandomInputs()) {
+    receive_array[0] = (15 << 24) + ctx.GetRandom().GetUInt(1 << 24);  // 00001111
+    receive_array[1] = (51 << 24) + ctx.GetRandom().GetUInt(1 << 24);  // 00110011
+    receive_array[2] = (85 << 24) + ctx.GetRandom().GetUInt(1 << 24);  // 01010101
+  } else {
     receive_array[0] = 0x0f139f14;  // 00001111 00010011 10011111 00010100
     receive_array[1] = 0x33083ee5;  // 00110011 00001000 00111110 11100101
     receive_array[2] = 0x5562eb41;  // 01010101 01100010 11101011 01000001
-  } else {
-    m_world->GetEnvironment().SetupInputs(ctx, input_array);
-    m_world->GetEnvironment().SetupInputs(ctx, receive_array);
   }
-
+  
   if (cur_depth > test_info.max_depth) test_info.max_depth = cur_depth;
 
   // Setup the organism we're working with now.

Modified: development/source/main/cEnvironment.cc
===================================================================
--- development/source/main/cEnvironment.cc	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/main/cEnvironment.cc	2006-12-19 21:11:08 UTC (rev 1149)
@@ -729,18 +729,31 @@
 }
 
 
-void cEnvironment::SetupInputs(cAvidaContext& ctx, tArray<int>& input_array) const
+void cEnvironment::SetupInputs(cAvidaContext& ctx, tArray<int>& input_array, bool random) const
 {
   input_array.Resize(m_input_size);
   
-  // Set the top 8 bits of the input buffer...
-  input_array[0] = 15 << 24;  // 00001111
-  input_array[1] = 51 << 24;  // 00110011
-  input_array[2] = 85 << 24;  // 01010101
-  
-  // And randomize the rest...
-  for (int i = 0; i < m_input_size; i++) {
-    input_array[i] += ctx.GetRandom().GetUInt(1 << 24);
+  if (random) {    
+    // Set the top 8 bits of the input buffer...
+    input_array[0] = 15 << 24;  // 00001111
+    input_array[1] = 51 << 24;  // 00110011
+    input_array[2] = 85 << 24;  // 01010101
+    
+    // And randomize the rest...
+    for (int i = 0; i < m_input_size; i++) {
+      input_array[i] += ctx.GetRandom().GetUInt(1 << 24);
+    }
+  } else {
+    // We make sure that all combinations of inputs are present.  This is
+    // done explicitly in the key columns... (0f, 33, and 55)
+    input_array[0] = 0x0f13149f;  // 00001111 00010011 00010100 10011111
+    input_array[1] = 0x3308e53e;  // 00110011 00001000 11100101 00111110
+    input_array[2] = 0x556241eb;  // 01010101 01100010 01000001 11101011
+    
+    // Fill out the rest with deterministically bit-shifted versions of the default 3
+    for (int i = 3; i < m_input_size; i++) {
+      input_array[i] = input_array[i % 3] << (i / 3);
+    }
   }
 }
 
@@ -774,20 +787,21 @@
     assert(cur_task != NULL);
     
     taskctx.SetTaskEntry(cur_task); // Set task entry in the context, so that tasks can reference task settings
-    const double task_quality = m_tasklib.TestOutput(taskctx);
     const int task_id = cur_task->GetID();
     const int task_cnt = task_count[task_id];
     const bool on_divide = taskctx.GetOnDivide();
     
-    // If this task wasn't performed, move on to the next one.
-    if (task_quality == 0.0) continue;
-    
     // Examine requisites on this reaction
     if (TestRequisites(cur_reaction->GetRequisites(), task_cnt, reaction_count, on_divide) == false) {
       continue;
     }
 
+    const double task_quality = m_tasklib.TestOutput(taskctx);
+
+    // If this task wasn't performed, move on to the next one.
+    if (task_quality == 0.0) continue;
     
+    
     // Mark this task as performed...
     result.MarkTask(task_id, task_quality);
 

Modified: development/source/main/cEnvironment.h
===================================================================
--- development/source/main/cEnvironment.h	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/main/cEnvironment.h	2006-12-19 21:11:08 UTC (rev 1149)
@@ -106,10 +106,10 @@
   bool LoadLine(cString line);  // Reads in a single environment configuration line
 
   // Interaction with the organisms
-  void SetupInputs(cAvidaContext& ctx, tArray<int>& input_array) const;
+  void SetupInputs(cAvidaContext& ctx, tArray<int>& input_array, bool random = true) const;
 
   bool TestInput(cReactionResult& result, const tBuffer<int>& inputs,
-                 const tBuffer<int>& outputs, const tArray<double>& resource_count ) const;
+                 const tBuffer<int>& outputs, const tArray<double>& resource_count) const;
 
   bool TestOutput(cAvidaContext& ctx, cReactionResult& result, cTaskContext& taskctx,
                   const tArray<int>& task_count, const tArray<int>& reaction_count,

Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/main/cOrganism.cc	2006-12-19 21:11:08 UTC (rev 1149)
@@ -190,7 +190,7 @@
   tBuffer<int>* received_messages_point = &m_received_messages;
   if (!m_world->GetConfig().SAVE_RECEIVED.Get()) received_messages_point = NULL;
   
-  cTaskContext taskctx(m_input_buf, m_output_buf, other_input_list, other_output_list, net_valid, 0, on_divide, received_messages_point);
+  cTaskContext taskctx(m_interface, m_input_buf, m_output_buf, other_input_list, other_output_list, net_valid, 0, on_divide, received_messages_point);
   m_phenotype.TestOutput(ctx, taskctx, resource_count, res_change, insts_triggered);
   m_interface->UpdateResources(res_change);
 
@@ -351,7 +351,7 @@
     m_output_buf.Add(value);
     tArray<double> res_change(resource_count.GetSize());
     tArray<int> insts_triggered;
-    cTaskContext taskctx(m_input_buf, m_output_buf, other_input_list, other_output_list, false, completed);
+    cTaskContext taskctx(m_interface, m_input_buf, m_output_buf, other_input_list, other_output_list, false, completed);
     m_phenotype.TestOutput(ctx, taskctx, resource_count, res_change, insts_triggered);
     m_interface->UpdateResources(res_change);
     
@@ -417,6 +417,28 @@
   fp << "---------------------------" << endl;
   m_hardware->PrintStatus(fp);
   m_phenotype.PrintStatus(fp);
+  fp << endl;
+
+  fp << setbase(16) << setfill('0');
+  
+  fp << "Input (env):";
+  for (int i = 0; i < m_input_buf.GetCapacity(); i++) {
+    int j = i; // temp holder, because GetInputAt self adjusts the input pointer
+    fp << " 0x" << setw(8) << m_interface->GetInputAt(j);
+  }
+  fp << endl;
+  
+  fp << "Input (buf):";
+  for (int i = 0; i < m_input_buf.GetNumStored(); i++) fp << " 0x" << setw(8) << m_input_buf[i];
+  fp << endl;
+
+  fp << "Output:     ";
+  for (int i = 0; i < m_output_buf.GetNumStored(); i++) fp << " 0x" << setw(8) << m_output_buf[i];
+  fp << endl;
+  
+  
+  fp << setfill(' ') << setbase(10);
+    
   fp << "---------------------------" << endl;
   fp << "ABOUT TO EXECUTE: " << next_name << endl;
 }

Modified: development/source/main/cTaskContext.h
===================================================================
--- development/source/main/cTaskContext.h	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/main/cTaskContext.h	2006-12-19 21:11:08 UTC (rev 1149)
@@ -10,6 +10,9 @@
 #ifndef cTaskContext_h
 #define cTaskContext_h
 
+#ifndef cOrgInterface_h
+#include "cOrgInterface.h"
+#endif
 #ifndef tBuffer_h
 #include "tBuffer.h"
 #endif
@@ -23,6 +26,7 @@
 class cTaskContext
 {
 private:
+  cOrgInterface* m_interface;
   const tBuffer<int>& input_buffer;
   const tBuffer<int>& output_buffer;
   const tList<tBuffer<int> >& other_input_buffers;
@@ -36,10 +40,12 @@
   cTaskEntry* task_entry;
 
 public:
-  cTaskContext(const tBuffer<int>& inputs, const tBuffer<int>& outputs, const tList<tBuffer<int> >& other_inputs,
-               const tList<tBuffer<int> >& other_outputs, bool in_net_valid, int in_net_completed, 
-               bool in_on_divide = false, tBuffer<int>* in_received_messages = NULL)
-    : input_buffer(inputs)
+  cTaskContext(cOrgInterface* interface, const tBuffer<int>& inputs, const tBuffer<int>& outputs,
+               const tList<tBuffer<int> >& other_inputs, const tList<tBuffer<int> >& other_outputs,
+               bool in_net_valid, int in_net_completed, bool in_on_divide = false,
+               tBuffer<int>* in_received_messages = NULL)
+    : m_interface(interface)
+    , input_buffer(inputs)
     , output_buffer(outputs)
     , other_input_buffers(other_inputs)
     , other_output_buffers(other_outputs)
@@ -52,6 +58,7 @@
   {
   }
   
+  inline int GetInputAt(int index) { return m_interface->GetInputAt(index); }
   inline const tBuffer<int>& GetInputBuffer() { return input_buffer; }
   inline const tBuffer<int>& GetOutputBuffer() { return output_buffer; }
   inline const tList<tBuffer<int> >& GetNeighborhoodInputBuffers() { return other_input_buffers; }

Modified: development/source/main/cTaskLib.cc
===================================================================
--- development/source/main/cTaskLib.cc	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/main/cTaskLib.cc	2006-12-19 21:11:08 UTC (rev 1149)
@@ -12,6 +12,7 @@
 
 #include "cArgSchema.h"
 #include "cEnvReqs.h"
+#include "tHashTable.h"
 
 #include <stdlib.h>
 extern "C" {
@@ -317,6 +318,9 @@
   else if (name == "match_number")
     Load_MatchNumber(name, info, envreqs);
 
+  if (name == "sort_inputs")
+    Load_SortInputs(name, info, envreqs);
+
 	// Communication Tasks
   if (name == "comm_echo")
     NewTask(name, "Echo of Neighbor's Input", &cTaskLib::Task_CommEcho, REQ_NEIGHBOR_INPUT);
@@ -1882,6 +1886,134 @@
 }
 
 
+void cTaskLib::Load_SortInputs(const cString& name, const cString& argstr, cEnvReqs& envreqs)
+{
+  cArgSchema schema(',',':');
+  
+  // Integer Arguments
+  schema.AddEntry("size", 0, cArgSchema::SCHEMA_INT); // Number of items to sort
+  schema.AddEntry("direction", 1, 0); // < 0 = Descending, Otherwise = Ascending
+  schema.AddEntry("contiguous", 2, 1); // 0 = No, Otherwise = Yes
+  // Double Arguments
+  schema.AddEntry("halflife", 0, cArgSchema::SCHEMA_DOUBLE);
+  
+  cArgContainer* args = cArgContainer::Load(argstr, schema);
+  if (args) {
+    envreqs.SetMinInputs(args->GetInt(0));
+    envreqs.SetMinOutputs(args->GetInt(0));
+    NewTask(name, "Sort Inputs", &cTaskLib::Task_SortInputs, 0, args);
+  }
+}
+
+double cTaskLib::Task_SortInputs(cTaskContext& ctx) const
+{
+  const cArgContainer& args = ctx.GetTaskEntry()->GetArguments();
+  const tBuffer<int>& input = ctx.GetInputBuffer();
+  const tBuffer<int>& output = ctx.GetOutputBuffer();
+  const int size = args.GetInt(0);
+  const int stored = output.GetNumStored();
+  
+  // if less than half, can't possibly reach threshold
+  if (stored <= (size / 2)) return 0.0;
+
+  tHashTable<int, int> valmap;
+  int score = 0;
+  int maxscore = 0;
+  
+  // add all valid inputs into the value map
+  for (int i = 0; i < size; i++) valmap.Add(ctx.GetInputAt(i), -1);
+  
+  int span_start = -1;
+  int span_end = stored;
+
+  if (args.GetInt(2)) { // Contiguous
+    // scan for the largest contiguous span
+    // - in the event of a tie, keep the first discovered
+    for (int i = 0; i < stored; i++) {
+      if (valmap.HasEntry(output[i])) {
+        int t_start = i;
+        while (++i < stored && valmap.HasEntry(output[i]));
+        if (span_start == -1 || (i - t_start) > (span_end - span_start)) {
+          span_start = t_start;
+          span_end = i;
+        }
+      }
+    }
+
+    // no span was found
+    if (span_start == -1) return 0.0;    
+  } else { // Scattered
+    // search for first valid entry
+    while (++span_start < stored && valmap.HasEntry(output[span_start]));
+    
+    // scanned past the end of the output, nothing to validate
+    if (span_start >= stored) return 0.0;
+  }
+  
+  // again, if span is less than half the size can't possibly reach threshold
+  if ((span_end - span_start) <= (size / 2)) return 0.0;
+  
+  // insertion sort span
+  // - count number of actual entries
+  // - count moves required
+  // - update valmap, tracking observed inputs
+  int sorted[size];
+  const bool ascending = (args.GetInt(1) >= 0);
+  int count = 1;
+
+  // store first value
+  valmap.SetValue(output[span_start], span_start);
+  sorted[0] = output[span_start];
+  
+  // iterate over the remaining span (discovered for contiguous, full output for scattered)
+  for (int i = span_start + 1; i < span_end; i++) {      
+    int value = output[i];
+    
+    // check for a dup or invalid output, skip it if so
+    int idx;
+    if (!valmap.Find(value, idx) || idx != -1) continue;
+    
+    maxscore += count; // count the maximum moves possible
+    count++; // iterate the observed count
+    valmap.SetValue(value,i); // save position, so that missing values can be determined later
+    
+    // sort value based on ascending for descending, counting moves
+    int j = count - 2;
+    while (j >= 0 && ((ascending && sorted[j] > value) || (!ascending && sorted[j] < value))) {
+      sorted[j + 1] = sorted[j];
+      j--;
+      score++;
+    }
+    sorted[j + 1] = value;
+  }
+  
+  // if not all of the inputs were observed
+  if (count < size) {
+    // iterate over all inputs
+    for (int i = 0; i < size; i++) {
+      int idx;
+      // if input was not observed
+      if (valmap.Find(ctx.GetInputAt(i), idx) && idx == -1) {
+        maxscore += count; // add to the maximum move count
+        score += count; // missing values, scored as maximally out of order
+        count++; // increment observed count
+      }
+    }
+  }
+  
+  double quality = 0.0;
+
+  // score of 50% expected with random output
+  // - only grant quality when less than 50% maximum moves are required
+  if (static_cast<double>(score) / static_cast<double>(maxscore) < 0.5) {
+    double halflife = -1.0 * fabs(args.GetDouble(0));
+    quality = pow(2.0, static_cast<double>(score) / halflife);
+  }
+  
+  return quality;
+}
+
+
 double cTaskLib::Task_CommEcho(cTaskContext& ctx) const
 {
   const int test_output = ctx.GetOutputBuffer()[0];

Modified: development/source/main/cTaskLib.h
===================================================================
--- development/source/main/cTaskLib.h	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/main/cTaskLib.h	2006-12-19 21:11:08 UTC (rev 1149)
@@ -226,6 +226,9 @@
   void Load_MatchNumber(const cString& name, const cString& argstr, cEnvReqs& envreqs);
   double Task_MatchNumber(cTaskContext& ctx) const;
 
+  void Load_SortInputs(const cString& name, const cString& argstr, cEnvReqs& envreqs);
+  double Task_SortInputs(cTaskContext& ctx) const;
+
   // Communication Tasks
   double Task_CommEcho(cTaskContext& ctx) const;
   double Task_CommNot(cTaskContext& ctx) const;

Modified: development/source/tools/tHashTable.h
===================================================================
--- development/source/tools/tHashTable.h	2006-12-18 18:10:08 UTC (rev 1148)
+++ development/source/tools/tHashTable.h	2006-12-19 21:11:08 UTC (rev 1149)
@@ -59,6 +59,8 @@
 #include "tList.h"
 #endif
 
+#include <stdlib.h>
+
 #if USE_tMemTrack
 # ifndef tMemTrack_h
 #  include "tMemTrack.h"
@@ -114,8 +116,9 @@
   
   // HASH_TYPE = int
   // Simply mod the into by the size of the hash table and hope for the best
-  int HashKey(const int & key) const {
-    return key % table_size;
+  int HashKey(const int& key) const
+  {
+    return abs(key % table_size);
   }
   
   // HASH_TYPE = cString




More information about the Avida-cvs mailing list