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

connel42 at myxo.css.msu.edu connel42 at myxo.css.msu.edu
Wed Aug 12 07:09:27 PDT 2009


Author: connel42
Date: 2009-08-12 10:09:27 -0400 (Wed, 12 Aug 2009)
New Revision: 3364

Modified:
   development/source/actions/EnvironmentActions.cc
   development/source/actions/PopulationActions.cc
   development/source/cpu/cHardwareCPU.cc
   development/source/cpu/cHardwareCPU.h
   development/source/main/cAvidaConfig.h
   development/source/main/cDeme.h
Log:
Added new generic sense and donate resource instructions, actions to set per-deme resource inflow and outflow, action to migrate members of a deme to another if the level of some resource is above some threshold

Modified: development/source/actions/EnvironmentActions.cc
===================================================================
--- development/source/actions/EnvironmentActions.cc	2009-08-11 12:54:54 UTC (rev 3363)
+++ development/source/actions/EnvironmentActions.cc	2009-08-12 14:09:27 UTC (rev 3364)
@@ -438,6 +438,46 @@
   }
 };
 
+/* Set the inflow of a given deme.  Currently only works for global (deme) resources.
+ 
+ Parameters:
+ deme id - the deme whose resource to set
+ name - the name of the resource
+ inflow - value to set as amount of resource added
+ 
+ */
+
+class cActionSetDemeResourceInflow : public cAction
+  {
+  private:
+    int m_demeid;
+    cString m_name;
+    double m_inflow;
+    
+  public:
+    cActionSetDemeResourceInflow(cWorld* world, const cString& args) : cAction(world, args), m_demeid(-1), m_name(""), m_inflow(0.0)
+    {
+      cString largs(args);
+      if (largs.GetSize()) m_demeid = largs.PopWord().AsInt();
+      if (largs.GetSize()) m_name = largs.PopWord();
+      if (largs.GetSize()) m_inflow = largs.PopWord().AsDouble();
+      
+      assert(m_inflow >= 0);
+      assert(m_demeid >= 0);
+      
+    }
+    
+    static const cString GetDescription() { return "Arguments: <int deme id> <string resource_name> <int inflow>"; }
+    
+    void Process(cAvidaContext& ctx)
+    {
+      m_world->GetEnvironment().SetResourceInflow(m_name, m_inflow);
+      //This doesn't actually update the rate in the population, so...
+      m_world->GetPopulation().GetDeme(m_demeid).GetDemeResources().SetInflow(m_name, m_inflow);
+    }
+  };
+
+
 class cActionSetResourceOutflow : public cAction
 {
 private:
@@ -464,6 +504,46 @@
   }
 };
 
+/* Set the outflow (decay) of a given deme.  Currently only works for global (deme) resources.
+ 
+Parameters:
+   deme id - the deme whose resource to set
+   name - the name of the resource
+   outflow - value to set as percentage of the resource decayed continuously
+ 
+*/
+
+class cActionSetDemeResourceOutflow : public cAction
+  {
+  private:
+    int m_demeid;
+    cString m_name;
+    double m_outflow;
+    
+  public:
+    cActionSetDemeResourceOutflow(cWorld* world, const cString& args) : cAction(world, args), m_demeid(-1), m_name(""), m_outflow(0.0)
+    {
+      cString largs(args);
+      if (largs.GetSize()) m_demeid = largs.PopWord().AsInt();
+      if (largs.GetSize()) m_name = largs.PopWord();
+      if (largs.GetSize()) m_outflow = largs.PopWord().AsDouble();
+      assert(m_demeid >= 0);
+      assert(m_outflow <= 1.0);
+      assert(m_outflow >= 0.0);
+    }
+    
+    static const cString GetDescription() { return "Arguments: <int deme id> <string resource_name> <int outflow>"; }
+    
+    void Process(cAvidaContext& ctx)
+    {
+      m_world->GetEnvironment().SetResourceOutflow(m_name, m_outflow);
+      //This doesn't actually update the rate in the population, so...
+      m_world->GetPopulation().GetDeme(m_demeid).GetDemeResources().SetDecay(m_name, 1-m_outflow);
+      
+    }
+  };
+
+
 class cActionSetEnvironmentInputs : public cAction
 {
 private:
@@ -1025,6 +1105,8 @@
 
   action_lib->Register<cActionSetResourceInflow>("SetResourceInflow");
   action_lib->Register<cActionSetResourceOutflow>("SetResourceOutflow");
+  action_lib->Register<cActionSetDemeResourceInflow>("SetDemeResourceInflow");
+  action_lib->Register<cActionSetDemeResourceOutflow>("SetDemeResourceOutflow");
 
   action_lib->Register<cActionSetEnvironmentInputs>("SetEnvironmentInputs");
   action_lib->Register<cActionSetEnvironmentRandomMask>("SetEnvironmentRandomMask");

Modified: development/source/actions/PopulationActions.cc
===================================================================
--- development/source/actions/PopulationActions.cc	2009-08-11 12:54:54 UTC (rev 3363)
+++ development/source/actions/PopulationActions.cc	2009-08-12 14:09:27 UTC (rev 3364)
@@ -3441,6 +3441,106 @@
 };
 
 
+/* This action migrates a configurable number of organisms from one deme to another if
+   the level of some global (deme) resource is above the configured threshold.
+ 
+Parameters: 3
+ - name of the resource.  This must be a deme-level global resource.
+ - threshold level for resource.  above this, organisms are migrated.
+ - number of organisms to migrate to a randomly-chosen deme.
+ 
+*/
+
+class cActionMigrateDemes : public cAction
+{
+  private:
+    cString m_res;
+    double m_thresh;
+    int m_numorgs;
+  public:
+    static const cString GetDescription() { return "Arguments: <string resource name><double failure_percent>"; }
+    
+    cActionMigrateDemes(cWorld* world, const cString& args) : cAction(world, args), m_thresh(0), m_numorgs(0)
+    {
+      cString largs(args);
+      if (largs.GetSize()) m_res = largs.PopWord();
+      if (largs.GetSize()) m_thresh = largs.PopWord().AsDouble();
+      if (largs.GetSize()) m_numorgs = largs.PopWord().AsInt();
+
+      assert(m_thresh >= 0);
+      assert(m_numorgs >= 0);
+      
+      assert(m_world->GetConfig().NUM_DEMES.Get() > 1);
+      
+      //Speculative execution will not work since we are moving organisms around.
+      assert(m_world->GetConfig().SPECULATIVE.Get() == 0);
+    }
+    
+    void Process(cAvidaContext& ctx)
+    {
+      int src_cellid, dest_cellid;
+      
+      for (int d = 0; d < m_world->GetPopulation().GetNumDemes(); d++) {
+        cDeme& deme = m_world->GetPopulation().GetDeme(d);
+        int deme_size = deme.GetWidth() * deme.GetHeight();
+        
+        const cResourceCount &res = deme.GetDemeResourceCount();
+        const int resid = res.GetResourceByName(m_res);
+        
+        if(resid == -1) {
+          //Resource doesn't exist for this deme.  This is a bad situation, but just go to next deme.
+          cerr << "Error: Resource \"" << m_res << "\" not defined for this deme" << endl;
+          continue;
+        }
+        
+        if(res.Get(resid) >= m_thresh) {
+          //Set the resource to zero
+          deme.AdjustResource(resid, (-1 * res.Get(resid)));
+          
+          //Pick a deme to move to
+          int target_demeid = m_world->GetRandom().GetInt(0, m_world->GetConfig().NUM_DEMES.Get()-1);
+          cDeme& target_deme = m_world->GetPopulation().GetDeme(target_demeid);
+          int target_deme_size = target_deme.GetWidth() * target_deme.GetHeight();
+          
+          //Migrate up to m_numorgs orgs
+          for(int i = 0; i < m_numorgs; i++) {
+            src_cellid = -1;
+            dest_cellid = -1;
+            
+            int counter = 0;
+            do {
+              src_cellid = m_world->GetRandom().GetInt(0, (deme.GetWidth() * deme.GetHeight())-1);
+              cout << ".";
+              counter++;
+            } while((counter < deme_size) && (!deme.GetCell(src_cellid).IsOccupied()));
+                        
+            counter = 0;
+            do {
+              dest_cellid = m_world->GetRandom().GetInt(0, target_deme_size - 1);
+              counter++;
+            } while((counter < target_deme_size) && (target_deme.GetCell(dest_cellid).IsOccupied())); 
+            
+            if( (src_cellid != -1) && (dest_cellid != -1) ) {
+            
+              m_world->GetPopulation().SwapCells(deme.GetCell(src_cellid), target_deme.GetCell(dest_cellid));
+              m_world->GetPopulation().MoveOrganisms(ctx, deme.GetCell(src_cellid), target_deme.GetCell(dest_cellid));
+              
+              deme.DecOrgCount();
+              target_deme.IncOrgCount();
+            }
+            
+            //migrate the organism from src_cell to dest cell
+          }
+          
+          
+        }
+        
+      } //End iterating through demes
+      
+    }
+};
+
+
 void RegisterPopulationActions(cActionLibrary* action_lib)
 {
   action_lib->Register<cActionInject>("Inject");
@@ -3561,4 +3661,5 @@
   action_lib->Register<cActionSwapCells>("swap_cells");
   action_lib->Register<cActionKillDemePercent>("KillDemePercent");
   action_lib->Register<cActionSetDemeTreatmentAges>("SetDemeTreatmentAges");
+  action_lib->Register<cActionMigrateDemes>("MigrateDemes");
 }

Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc	2009-08-11 12:54:54 UTC (rev 3363)
+++ development/source/cpu/cHardwareCPU.cc	2009-08-12 14:09:27 UTC (rev 3364)
@@ -229,6 +229,13 @@
     tInstLibEntry<tMethod>("sense", &cHardwareCPU::Inst_SenseLog2, nInstFlag::STALL),           // If you add more sense instructions
     tInstLibEntry<tMethod>("sense-unit", &cHardwareCPU::Inst_SenseUnit, nInstFlag::STALL),      // and want to keep stats, also add
     tInstLibEntry<tMethod>("sense-m100", &cHardwareCPU::Inst_SenseMult100, nInstFlag::STALL),   // the names to cStats::cStats() @JEB
+    
+    tInstLibEntry<tMethod>("sense-resource0", &cHardwareCPU::Inst_SenseResource0, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("sense-resource1", &cHardwareCPU::Inst_SenseResource1, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("sense-resource2", &cHardwareCPU::Inst_SenseResource2, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("sense-faced-resource0", &cHardwareCPU::Inst_SenseFacedResource0, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("sense-faced-resource1", &cHardwareCPU::Inst_SenseFacedResource1, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("sense-faced-resource2", &cHardwareCPU::Inst_SenseFacedResource2, nInstFlag::STALL),
 
     tInstLibEntry<tMethod>("if-resources", &cHardwareCPU::Inst_IfResources, nInstFlag::STALL),
     tInstLibEntry<tMethod>("collect", &cHardwareCPU::Inst_Collect, nInstFlag::STALL),
@@ -263,6 +270,9 @@
     tInstLibEntry<tMethod>("request-energy-off", &cHardwareCPU::Inst_RequestEnergyFlagOff, nInstFlag::STALL),
     tInstLibEntry<tMethod>("increase-energy-donation", &cHardwareCPU::Inst_IncreaseEnergyDonation, nInstFlag::STALL),    
     tInstLibEntry<tMethod>("decrease-energy-donation", &cHardwareCPU::Inst_DecreaseEnergyDonation, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("donate-resource0", &cHardwareCPU::Inst_DonateResource0, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("donate-resource1", &cHardwareCPU::Inst_DonateResource1, nInstFlag::STALL),
+    tInstLibEntry<tMethod>("donate-resource2", &cHardwareCPU::Inst_DonateResource2, nInstFlag::STALL),
     tInstLibEntry<tMethod>("IObuf-add1", &cHardwareCPU::Inst_IOBufAdd1, nInstFlag::STALL),
     tInstLibEntry<tMethod>("IObuf-add0", &cHardwareCPU::Inst_IOBufAdd0, nInstFlag::STALL),
 
@@ -3510,6 +3520,57 @@
   // Note that we are converting <double> resources to <int> register values
 }
 
+
+bool cHardwareCPU::Inst_SenseResource0(cAvidaContext& ctx)
+{
+  return DoSenseResourceX(REG_BX, m_organism->GetCellID(), 0);
+}
+
+bool cHardwareCPU::Inst_SenseResource1(cAvidaContext& ctx)
+{
+  return DoSenseResourceX(REG_BX, m_organism->GetCellID(), 1);
+}
+
+bool cHardwareCPU::Inst_SenseResource2(cAvidaContext& ctx)
+{
+  return DoSenseResourceX(REG_BX, m_organism->GetCellID(), 2);
+}
+
+bool cHardwareCPU::Inst_SenseFacedResource0(cAvidaContext& ctx)
+{
+  return DoSenseResourceX(REG_BX, m_world->GetPopulation().GetCell(m_organism->GetCellID()).GetCellFaced().GetID(), 0);
+}
+
+bool cHardwareCPU::Inst_SenseFacedResource1(cAvidaContext& ctx)
+{
+  return DoSenseResourceX(REG_BX, m_world->GetPopulation().GetCell(m_organism->GetCellID()).GetCellFaced().GetID(), 1);
+}
+
+bool cHardwareCPU::Inst_SenseFacedResource2(cAvidaContext& ctx)
+{
+  return DoSenseResourceX(REG_BX, m_world->GetPopulation().GetCell(m_organism->GetCellID()).GetCellFaced().GetID(), 2);
+}
+
+
+bool cHardwareCPU::DoSenseResourceX(int reg_to_set, int cell_id, int resid)
+{
+  assert(resid >= 0);
+  
+  cPopulation& pop = m_world->GetPopulation();
+  
+  const tArray<double> & res_count = pop.GetCellResources(cell_id) +
+  pop.GetDemeCellResources(pop.GetCell(cell_id).GetDemeID(), cell_id);
+  
+  // Make sure we have the resource requested
+  if (resid >= res_count.GetSize()) return false;
+  
+  GetRegister(reg_to_set) = (int) res_count[resid];
+  
+  return true; 
+  
+}
+
+
 /* Convert modifying NOPs to the index of a resource. If there are fewer 
  * than the number of NOPs required to specify a resource, find the subset 
  * of resources.  (Motivation: can evolve to be more specific if there is 
@@ -3789,7 +3850,7 @@
 // energy may be lost in transfer
 void cHardwareCPU::DoEnergyDonateAmount(cOrganism* to_org, const double amount)
 {
-  double losspct = m_world->GetConfig().ENERGY_SHARING_LOSS.Get();
+  double losspct = m_world->GetConfig().RESOURCE_SHARING_LOSS.Get();
   
   assert(to_org != NULL);
   assert(amount >= 0);
@@ -4962,6 +5023,110 @@
 } //End Inst_DecreaseEnergyDonation()
 
 
+// Move a fraction of the given resource present at the current cell to the specified cell.
+// Note: This function doesn't work with deme-level resources.
+void cHardwareCPU::DoResourceDonatePercent(const int to_cell, const int resource_id, const double frac_resource_given)
+{
+  assert(to_cell >= 0);
+  assert(resource_id >= 0);
+  assert(frac_resource_given >= 0);
+  assert(frac_resource_given <= 1);
+  
+  const tArray<double> &resources = m_organism->GetOrgInterface().GetResources(); 
+  if(resource_id >= resources.GetSize()) return;
+  
+  const double amount = max(0.0, frac_resource_given * resources[resource_id]);
+  
+  DoResourceDonateAmount(to_cell, resource_id, amount);
+  
+} //End DoResourceDonatePercent()
+
+
+// Donate a portion of the given resource present at the current cell to the specified cell.
+// Note: This function doesn't work with deme-level resources.
+void cHardwareCPU::DoResourceDonateAmount(const int to_cell, const int resource_id, const double amount)
+{  
+  assert(to_cell >= 0);
+  assert(amount >= 0);
+  assert(resource_id >= 0);
+  
+  const tArray<double> &src_resources = m_organism->GetOrgInterface().GetResources();
+  const tArray<double> &dest_resources = m_world->GetPopulation().GetCellResources(to_cell);
+  
+  assert(resource_id < src_resources.GetSize());
+  assert(resource_id < dest_resources.GetSize());
+  
+  const double donation = min(amount, src_resources[resource_id]);
+  const double decay = m_world->GetConfig().RESOURCE_SHARING_LOSS.Get();
+  
+  assert(decay >= 0);
+  assert(decay <= 1);
+  
+  tArray<double> src_change;
+  tArray<double> dest_change;
+  
+  src_change.Resize(src_resources.GetSize(), 0);
+  dest_change.Resize(dest_resources.GetSize(), 0);
+  
+  src_change[resource_id] = -1 * donation;
+  dest_change[resource_id] = (1 - decay) * donation;
+  
+  m_organism->GetOrgInterface().UpdateResources(src_change);
+  m_world->GetPopulation().UpdateCellResources(dest_change, to_cell);
+  
+} //End DoResourceDonateAmount()
+
+
+//Donate a fraction of nop-specified resource at organism's location to cell faced
+bool cHardwareCPU::DonateResourceX(cAvidaContext& ctx, const int res_id)
+{
+  assert(m_organism != 0);
+  assert(res_id >= 0);
+  
+  const double pct = 0.1;
+  
+  int current_cell, faced_cell;
+  
+  current_cell = m_organism->GetCellID();
+	
+  if(current_cell == -1) {
+    return false;
+  }
+  
+  cPopulation& pop = m_world->GetPopulation();
+  faced_cell = pop.GetCell(current_cell).GetCellFaced().GetID();
+  
+  if(faced_cell == -1) {
+    return false;
+  }
+  
+  DoResourceDonatePercent(faced_cell, res_id, pct);
+  
+  return true;
+  
+} //End DonateResourceX()
+
+
+//Donate a fraction of nop-specified resource at organism's location to cell faced
+bool cHardwareCPU::Inst_DonateResource0(cAvidaContext& ctx)
+{
+  return DonateResourceX(ctx ,0);  
+} //End Inst_DonateResource0()
+
+
+//Donate a fraction of nop-specified resource at organism's location to cell faced
+bool cHardwareCPU::Inst_DonateResource1(cAvidaContext& ctx)
+{
+  return DonateResourceX(ctx, 1);
+} //End Inst_DonateResource1()
+
+//Donate a fraction of nop-specified resource at organism's location to cell faced
+bool cHardwareCPU::Inst_DonateResource2(cAvidaContext& ctx)
+{
+  return DonateResourceX(ctx, 2);
+} //End Inst_DonateResource2()
+
+
 bool cHardwareCPU::Inst_SearchF(cAvidaContext& ctx)
 {
   ReadLabel();

Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h	2009-08-11 12:54:54 UTC (rev 3363)
+++ development/source/cpu/cHardwareCPU.h	2009-08-12 14:09:27 UTC (rev 3364)
@@ -493,6 +493,13 @@
   bool Inst_SenseUnit(cAvidaContext& ctx);
   bool Inst_SenseMult100(cAvidaContext& ctx);
   bool DoSense(cAvidaContext& ctx, int conversion_method, double base);
+  bool DoSenseResourceX(int reg_to_set, int cell_id, int resid);
+  bool Inst_SenseResource0(cAvidaContext& ctx);
+  bool Inst_SenseResource1(cAvidaContext& ctx);
+  bool Inst_SenseResource2(cAvidaContext& ctx);
+  bool Inst_SenseFacedResource0(cAvidaContext& ctx);
+  bool Inst_SenseFacedResource1(cAvidaContext& ctx);
+  bool Inst_SenseFacedResource2(cAvidaContext& ctx);
   
   // Resources
   bool FindModifiedResource(int& start_index, int& end_index, int& spec_id);
@@ -536,6 +543,13 @@
   bool Inst_IncreaseEnergyDonation(cAvidaContext& ctx);
   bool Inst_DecreaseEnergyDonation(cAvidaContext& ctx);
   
+  void DoResourceDonatePercent(const int to_cell, const int resource_id, const double frac_resource_given);
+  void DoResourceDonateAmount(const int to_cell, const int resource_id, const double amount);
+  bool DonateResourceX(cAvidaContext& ctx, const int res_id);
+  bool Inst_DonateResource0(cAvidaContext& ctx);
+  bool Inst_DonateResource1(cAvidaContext& ctx);
+  bool Inst_DonateResource2(cAvidaContext& ctx);
+  
   bool Inst_SearchF(cAvidaContext& ctx);
   bool Inst_SearchB(cAvidaContext& ctx);
   bool Inst_MemSize(cAvidaContext& ctx);

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2009-08-11 12:54:54 UTC (rev 3363)
+++ development/source/main/cAvidaConfig.h	2009-08-12 14:09:27 UTC (rev 3364)
@@ -549,7 +549,7 @@
   CONFIG_ADD_VAR(ENERGY_SHARING_METHOD, int, 0, "Method for sharing energy.  0=receiver must actively receive/request, 1=energy pushed on receiver");
   CONFIG_ADD_VAR(ENERGY_SHARING_PCT, double, 0.0, "Percent of energy to share");
   CONFIG_ADD_VAR(ENERGY_SHARING_INCREMENT, double, 0.01, "Amount to change percent energy shared");
-  CONFIG_ADD_VAR(ENERGY_SHARING_LOSS, double, 0.0, "Percent of shared energy lost in transfer");
+  CONFIG_ADD_VAR(RESOURCE_SHARING_LOSS, double, 0.0, "Fraction of shared resource lost in transfer");
   CONFIG_ADD_VAR(ENERGY_SHARING_UPDATE_METABOLIC, bool, 0, "0/1 (off/on) - Whether to update an organism's metabolic rate on donate or reception/application of energy");
   CONFIG_ADD_VAR(LOG_ENERGY_SHARING, bool, 0, "Whether or not to log energy shares.  0/1 (off/on)");
   

Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h	2009-08-11 12:54:54 UTC (rev 3363)
+++ development/source/main/cDeme.h	2009-08-12 14:09:27 UTC (rev 3364)
@@ -260,6 +260,7 @@
 	void OrganismDeath(cPopulationCell& cell);
   
   const cResourceCount& GetDemeResourceCount() const { return deme_resource_count; }
+  cResourceCount& GetDemeResources() { return deme_resource_count; }
 	void SetResource(int id, double new_level) { deme_resource_count.Set(id, new_level); }
   double GetSpatialResource(int rel_cellid, int resource_id) const;
   void AdjustSpatialResource(int rel_cellid, int resource_id, double amount);




More information about the Avida-cvs mailing list