[Avida-SVN] r3151 - in development/source: cpu main
dk at myxo.css.msu.edu
dk at myxo.css.msu.edu
Fri Feb 20 08:10:37 PST 2009
Author: dk
Date: 2009-02-20 11:10:36 -0500 (Fri, 20 Feb 2009)
New Revision: 3151
Modified:
development/source/cpu/cHardwareCPU.cc
development/source/cpu/cHardwareCPU.h
development/source/cpu/cTestCPUInterface.h
development/source/main/cDeme.cc
development/source/main/cDeme.h
development/source/main/cOrgInterface.h
development/source/main/cOrganism.cc
development/source/main/cOrganism.h
development/source/main/cPopulationCell.cc
development/source/main/cPopulationCell.h
development/source/main/cPopulationInterface.cc
development/source/main/cPopulationInterface.h
Log:
Merged instruction-level message broadcasting in with energy-sharing broadcasting. There are now four different broadcast instructions that vary in terms of how "strong" the broadcast is (that is, how many hops away they'll broadcast to).
Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/cpu/cHardwareCPU.cc 2009-02-20 16:10:36 UTC (rev 3151)
@@ -107,6 +107,20 @@
tInstLibEntry<tMethod>("if-grt-X", &cHardwareCPU::Inst_IfGrX),
tInstLibEntry<tMethod>("if-equ-X", &cHardwareCPU::Inst_IfEquX),
+ // Probabilistic ifs.
+ tInstLibEntry<tMethod>("if-p-0.125", &cHardwareCPU::Inst_IfP0p125, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("if-p-0.25", &cHardwareCPU::Inst_IfP0p25, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("if-p-0.50", &cHardwareCPU::Inst_IfP0p50, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("if-p-0.75", &cHardwareCPU::Inst_IfP0p75, nInstFlag::STALL),
+
+ // The below series of conditionals extend the traditional Avida single-instruction-skip
+ // to a block, or series of instructions.
+ tInstLibEntry<tMethod>("if-less.end", &cHardwareCPU::Inst_IfLessEnd, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("if-n-equ.end", &cHardwareCPU::Inst_IfNotEqualEnd, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("if->=.end", &cHardwareCPU::Inst_IfGrtEquEnd, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("else", &cHardwareCPU::Inst_Else, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("end-if", &cHardwareCPU::Inst_EndIf, nInstFlag::STALL),
+
tInstLibEntry<tMethod>("jump-f", &cHardwareCPU::Inst_JumpF),
tInstLibEntry<tMethod>("jump-b", &cHardwareCPU::Inst_JumpB),
tInstLibEntry<tMethod>("call", &cHardwareCPU::Inst_Call),
@@ -453,7 +467,11 @@
// Messaging
tInstLibEntry<tMethod>("send-msg", &cHardwareCPU::Inst_SendMessage, nInstFlag::STALL),
tInstLibEntry<tMethod>("retrieve-msg", &cHardwareCPU::Inst_RetrieveMessage, nInstFlag::STALL),
-
+ tInstLibEntry<tMethod>("bcast1", &cHardwareCPU::Inst_Broadcast1, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("bcast2", &cHardwareCPU::Inst_Broadcast2, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("bcast4", &cHardwareCPU::Inst_Broadcast4, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("bcast8", &cHardwareCPU::Inst_Broadcast8, nInstFlag::STALL),
+
// Alarms
tInstLibEntry<tMethod>("send-alarm-msg-local", &cHardwareCPU::Inst_Alarm_MSG_local, nInstFlag::STALL),
tInstLibEntry<tMethod>("send-alarm-msg-multihop", &cHardwareCPU::Inst_Alarm_MSG_multihop, nInstFlag::STALL),
@@ -512,6 +530,10 @@
tInstLibEntry<tMethod>("hard-reset", &cHardwareCPU::Inst_HardReset, nInstFlag::STALL),
tInstLibEntry<tMethod>("get-cycles", &cHardwareCPU::Inst_GetCycles, nInstFlag::STALL),
+ // Neighborhood-sensing instructions
+ tInstLibEntry<tMethod>("get-neighborhood", &cHardwareCPU::Inst_GetNeighborhood, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("if-neighborhood-changed", &cHardwareCPU::Inst_IfNeighborhoodChanged, nInstFlag::STALL),
+
// Must always be the last instruction in the array
tInstLibEntry<tMethod>("NULL", &cHardwareCPU::Inst_Nop, 0, "True no-operation instruction: does nothing"),
};
@@ -1947,6 +1969,38 @@
return true;
}
+
+bool cHardwareCPU::Inst_IfP0p125(cAvidaContext& ctx) {
+ if(m_world->GetRandom().P(0.875)) {
+ IP().Advance();
+ }
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_IfP0p25(cAvidaContext& ctx) {
+ if(m_world->GetRandom().P(0.75)) {
+ IP().Advance();
+ }
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_IfP0p50(cAvidaContext& ctx) {
+ if(m_world->GetRandom().P(0.5)) {
+ IP().Advance();
+ }
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_IfP0p75(cAvidaContext& ctx) {
+ if(m_world->GetRandom().P(0.25)) {
+ IP().Advance();
+ }
+ return true;
+}
+
bool cHardwareCPU::Inst_JumpF(cAvidaContext& ctx)
{
ReadLabel();
@@ -4461,7 +4515,7 @@
cOrgMessage msg(m_organism);
// Could set the data field of the message to be the multiplier
- m_organism->BroadcastMessage(ctx, msg);
+ m_organism->BroadcastMessage(ctx, msg, m_world->GetConfig().MESSAGE_BCAST_RADIUS.Get());
m_organism->GetPhenotype().SetIsEnergyRequestor();
m_organism->GetPhenotype().IncreaseNumEnergyRequests();
@@ -7879,3 +7933,158 @@
GetRegister(FindModifiedRegister(REG_BX)) = m_cycle_counter;
return true;
}
+
+
+//! Loads the current neighborhood into the organism's memory.
+bool cHardwareCPU::Inst_GetNeighborhood(cAvidaContext& ctx) {
+ assert(m_organism != 0);
+ m_organism->LoadNeighborhood();
+ return true;
+}
+
+
+//! Test if the current neighborhood has changed from that in the organism's memory.
+bool cHardwareCPU::Inst_IfNeighborhoodChanged(cAvidaContext& ctx) {
+ assert(m_organism != 0);
+ if(!m_organism->HasNeighborhoodChanged()) {
+ IP().Advance();
+ }
+
+ return true;
+}
+
+
+/*! Find the first occurence of the passed-in instruction from the IP() forward,
+ wrapping around the genome as required. If the given instruction is not in the
+ genome, return the starting position.
+ */
+cHeadCPU cHardwareCPU::Find(const char* instr) {
+ cHeadCPU ptr(IP());
+ const int current = ptr.GetPosition();
+ ptr.Advance();
+ while(ptr.GetPosition() != current) {
+ ptr.Advance();
+ if(m_inst_set->GetName(ptr.GetInst())==instr) {
+ break;
+ }
+ }
+ return ptr;
+}
+
+
+bool cHardwareCPU::Inst_IfLessEnd(cAvidaContext& ctx) {
+ const int x = FindModifiedRegister(REG_BX);
+ const int y = FindNextRegister(x);
+
+ if(GetRegister(x) >= GetRegister(y)) { Else_TopHalf(); }
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_IfNotEqualEnd(cAvidaContext& ctx) {
+ const int x = FindModifiedRegister(REG_BX);
+ const int y = FindNextRegister(x);
+
+ if(GetRegister(x) == GetRegister(y)) { Else_TopHalf(); }
+ return true;
+}
+
+
+bool cHardwareCPU::Inst_IfGrtEquEnd(cAvidaContext& ctx) {
+ const int x = FindModifiedRegister(REG_BX);
+ const int y = FindNextRegister(x);
+
+ if(GetRegister(x) < GetRegister(y)) { Else_TopHalf(); }
+ return true;
+}
+
+
+/*! This is the top-half of the else instruction, meant to be executed if the if
+ condition evaluates to false.
+ */
+void cHardwareCPU::Else_TopHalf() {
+ cHeadCPU else_head = Find("else");
+ cHeadCPU endif_head = Find("endif");
+
+ // Condition failed. If there's an else-clause, jump to it.
+ // If there isn't an else-clause, try to jump to the endif.
+ // Note that the IP is unconditionally advanced *after* this instruction
+ // has executed. If there is no else or endif, advance one instruction.
+ if(else_head.GetPosition() != IP().GetPosition()) {
+ IP().Set(else_head);
+ } else if(endif_head.GetPosition() != IP().GetPosition()) {
+ IP().Set(endif_head);
+ } else {
+ // No else or endif. Advance past the next instruction (as normal).
+ IP().Advance();
+ }
+}
+
+
+/*! The only way that this instruction can be executed is if the if passed, or
+ if there was no if. In both cases, we're going to jump to the first <end-if>, or
+ skip one instruction.
+ */
+bool cHardwareCPU::Inst_Else(cAvidaContext& ctx) {
+ cHeadCPU endif_head = Find("endif");
+ if(endif_head.GetPosition() != IP().GetPosition()) {
+ // If the <end-if> is somewhere else, jump to it.
+ IP().Set(endif_head);
+ } else {
+ // Otherwise, just skip one instruction.
+ IP().Advance();
+ }
+ return true;
+}
+
+/*! This is just a placeholder; it has no functionality of its own.
+ */
+bool cHardwareCPU::Inst_EndIf(cAvidaContext& ctx) {
+ return true;
+}
+
+
+/*! A generic broadcast method, to simplify the development of different range
+ broadcasts.
+ */
+bool cHardwareCPU::BroadcastX(cAvidaContext& ctx, int depth) {
+ const int label_reg = FindModifiedRegister(REG_BX);
+ const int data_reg = FindNextRegister(label_reg);
+
+ cOrgMessage msg = cOrgMessage(m_organism);
+ msg.SetLabel(GetRegister(label_reg));
+ msg.SetData(GetRegister(data_reg));
+ return m_organism->BroadcastMessage(ctx, msg, depth);
+}
+
+
+/*! A single-hop broadcast instruction - send a message to all 1-hop neighbors
+ of this organism.
+ */
+bool cHardwareCPU::Inst_Broadcast1(cAvidaContext& ctx) {
+ return BroadcastX(ctx, 1);
+}
+
+
+/*! A double-hop broadcast instruction - send a message to all 2-hop neighbors
+ of this organism.
+ */
+bool cHardwareCPU::Inst_Broadcast2(cAvidaContext& ctx) {
+ return BroadcastX(ctx, 2);
+}
+
+
+/*! Another broadcast instruction variant - send a message to all 4-hop neighbors
+ of this organism.
+ */
+bool cHardwareCPU::Inst_Broadcast4(cAvidaContext& ctx) {
+ return BroadcastX(ctx, 4);
+}
+
+
+/*! Another broadcast instruction variant - send a message to all 8-hop neighbors
+ of this organism.
+ */
+bool cHardwareCPU::Inst_Broadcast8(cAvidaContext& ctx) {
+ return BroadcastX(ctx, 8);
+}
Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/cpu/cHardwareCPU.h 2009-02-20 16:10:36 UTC (rev 3151)
@@ -339,6 +339,21 @@
bool Inst_IfANotEqC(cAvidaContext& ctx);
bool Inst_IfGrX(cAvidaContext& ctx);
bool Inst_IfEquX(cAvidaContext& ctx);
+
+ // Probabilistic ifs.
+ bool Inst_IfP0p125(cAvidaContext& ctx);
+ bool Inst_IfP0p25(cAvidaContext& ctx);
+ bool Inst_IfP0p50(cAvidaContext& ctx);
+ bool Inst_IfP0p75(cAvidaContext& ctx);
+
+ // If-less-else-if, else, endif
+ cHeadCPU Find(const char* instr);
+ void Else_TopHalf();
+ bool Inst_IfLessEnd(cAvidaContext& ctx);
+ bool Inst_IfNotEqualEnd(cAvidaContext& ctx);
+ bool Inst_IfGrtEquEnd(cAvidaContext& ctx);
+ bool Inst_Else(cAvidaContext& ctx);
+ bool Inst_EndIf(cAvidaContext& ctx);
bool Inst_JumpF(cAvidaContext& ctx);
bool Inst_JumpB(cAvidaContext& ctx);
@@ -646,7 +661,7 @@
bool Inst_Numberate24(cAvidaContext& ctx) { return Do_Numberate(ctx, 24); };
bool Do_Numberate(cAvidaContext& ctx, int num_bits=0);
- // Helper functions //
+ // Helper functions //
bool IsActivePromoter();
void NextPromoter();
int Numberate(int _pos, int _dir, int _num_bits = 0);
@@ -663,6 +678,11 @@
//// Messaging ////
bool Inst_SendMessage(cAvidaContext& ctx);
bool Inst_RetrieveMessage(cAvidaContext& ctx);
+ bool BroadcastX(cAvidaContext& ctx, int depth);
+ bool Inst_Broadcast1(cAvidaContext& ctx);
+ bool Inst_Broadcast2(cAvidaContext& ctx);
+ bool Inst_Broadcast4(cAvidaContext& ctx);
+ bool Inst_Broadcast8(cAvidaContext& ctx);
//// Alarm ////
bool Inst_Alarm_MSG_local(cAvidaContext& ctx);
@@ -672,7 +692,6 @@
bool Inst_Alarm_Label(cAvidaContext& ctx);
bool Jump_To_Alarm_Label(int jump_label);
-
//// Placebo ////
bool Inst_Skip(cAvidaContext& ctx);
@@ -755,6 +774,13 @@
std::pair<unsigned int, unsigned int> m_flash_info;
//! Cycle timer; counts the number of cycles this virtual CPU has executed.
unsigned int m_cycle_counter;
+
+ // -------- Neighborhood-sensing support --------
+public:
+ //! Loads the current neighborhood into the organism's memory.
+ bool Inst_GetNeighborhood(cAvidaContext& ctx);
+ //! Test if the current neighborhood has changed from that in the organism's memory.
+ bool Inst_IfNeighborhoodChanged(cAvidaContext& ctx);
};
Modified: development/source/cpu/cTestCPUInterface.h
===================================================================
--- development/source/cpu/cTestCPUInterface.h 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/cpu/cTestCPUInterface.h 2009-02-20 16:10:36 UTC (rev 3151)
@@ -92,7 +92,7 @@
int GetFacing() { return 0; }
bool SendMessage(cOrgMessage& msg) { return false; }
bool SendMessage(cOrganism* recvr, cOrgMessage& msg) { return false; }
- bool BroadcastMessage(cOrgMessage& msg) { return false; }
+ bool BroadcastMessage(cOrgMessage& msg, int depth) { return false; }
bool BcastAlarm(int jump_label, int bcast_range) { return false; }
void DivideOrgTestamentAmongDeme(double value) {;}
void SendFlash() { }
Modified: development/source/main/cDeme.cc
===================================================================
--- development/source/main/cDeme.cc 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cDeme.cc 2009-02-20 16:10:36 UTC (rev 3151)
@@ -812,62 +812,3 @@
// assert(false); // slots must be of equal size and fit perfectally in deme lifetime
return 0;
}
-
-/* Place the absolute IDs of all cells surrounding the given cell id within the given radius into vector cells */
-void cDeme::GetSurroundingCellIds(tVector<int> &cells, const int absolute_cell_id, const int radius) {
- assert(cell_ids[0] <= absolute_cell_id);
- assert(absolute_cell_id <= cell_ids[cell_ids.GetSize()-1]);
- assert(radius >= 0);
-
- const int relative_cell_id = GetRelativeCellID(absolute_cell_id);
- const int geometry = m_world->GetConfig().WORLD_GEOMETRY.Get();
- const int width = GetWidth();
- const int height = GetHeight();
- const std::pair<int, int> coords = GetCellPosition(absolute_cell_id);
- const int curr_x = coords.first;
- const int curr_y = coords.second;
- int cid, acid;
- int x2, y2;
-
- //Note: this code currently supports a grid or torus
- assert(geometry == nGeometry::GRID || geometry == nGeometry::TORUS);
-
- if(geometry == nGeometry::GRID) {
- for(int y = curr_y - radius; y <= curr_y + radius; y++) {
- for(int x = curr_x - radius; x <= curr_x + radius; x++) {
- cid = y * width + x;
- acid = GetAbsoluteCellID(cid);
- if(y >= 0 && y < height && x >= 0 && x < width && cid != relative_cell_id) {
- cells.Add(acid);
- }
- }
- }
- } //End if world is a grid
- else if(geometry == nGeometry::TORUS) {
- for(int y = curr_y - radius; y <= curr_y + radius; y++) {
- for(int x = curr_x - radius; x <= curr_x + radius; x++) {
- x2 = x; y2 = y;
-
- if(x2 < 0) {
- x2 = x2 + width;
- } else if(x2 >= width) {
- x2 = x2 - width;
- }
-
- if(y2 < 0) {
- y2 = y2 + height;
- } else if(y2 >= height) {
- y2 = y2 - height;
- }
-
- cid = y2 * width + x2;
- acid = GetAbsoluteCellID(cid);
-
- if(cid != relative_cell_id) {
- cells.Add(acid);
- }
- }
- }
- } //End if world is a torus
-
-} //End GetSurroundingCellIds()
Modified: development/source/main/cDeme.h
===================================================================
--- development/source/main/cDeme.h 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cDeme.h 2009-02-20 16:10:36 UTC (rev 3151)
@@ -347,9 +347,6 @@
void IncreaseEnergyDonated(double amount) { assert(amount >=0); total_energy_donated += amount; }
void IncreaseEnergyReceived(double amount) { assert(amount >=0); total_energy_received += amount; }
void IncreaseEnergyApplied(double amount) { assert(amount >=0); total_energy_applied += amount; }
-
-
- void GetSurroundingCellIds(tVector<int> &cells, const int absolute_cell_id, const int radius);
};
#endif
Modified: development/source/main/cOrgInterface.h
===================================================================
--- development/source/main/cOrgInterface.h 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cOrgInterface.h 2009-02-20 16:10:36 UTC (rev 3151)
@@ -102,7 +102,7 @@
virtual bool UpdateMerit(double new_merit) = 0;
virtual bool TestOnDivide() = 0;
virtual bool SendMessage(cOrgMessage& msg) = 0;
- virtual bool BroadcastMessage(cOrgMessage& msg) = 0;
+ virtual bool BroadcastMessage(cOrgMessage& msg, int depth) = 0;
virtual bool BcastAlarm(int jump_jabel, int bcast_range) = 0;
virtual void DivideOrgTestamentAmongDeme(double value) = 0;
virtual void SendFlash() = 0;
Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cOrganism.cc 2009-02-20 16:10:36 UTC (rev 3151)
@@ -781,31 +781,29 @@
}
-// Broadcast a message - slightly modified version of SendMessage
-bool cOrganism::BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg)
-{
+/*! Broadcast a message to all organisms out to the given depth. */
+bool cOrganism::BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg, int depth) {
assert(m_interface);
InitMessaging();
-
- // If we're able to succesfully send the message...
- if(m_interface->BroadcastMessage(msg)) {
- // If we're remembering messages
+
+ if(m_interface->BroadcastMessage(msg, depth)) {
+ // If we're remembering messages
if (m_world->GetConfig().ORGANISMS_REMEMBER_MESSAGES.Get()) {
// save it...
m_msg->sent.push_back(msg);
// and set the receiver-pointer of this message to NULL. We don't want to
// walk this list later thinking that the receivers are still around.
m_msg->sent.back().SetReceiver(0);
- }
- // stat-tracking... NOTE: this has receiver not specified, so may be a problem for predicates
+ }
+ // stat-tracking... NOTE: this has receiver not specified, so may be a problem for predicates
m_world->GetStats().SentMessage(msg);
// check to see if we've performed any tasks...NOTE: this has receiver not specified, so may be a problem for tasks that care
DoOutput(ctx);
return true;
}
-
- return false;
-} //End BroadcastMessage()
+
+ return false;
+}
void cOrganism::ReceiveMessage(cOrgMessage& msg)
@@ -929,3 +927,40 @@
m_world->GetStats().SentFlash(*this);
DoOutput(ctx);
}
+
+
+cOrganism::Neighborhood cOrganism::GetNeighborhood() {
+ Neighborhood neighbors;
+ for(int i=0; i<GetNeighborhoodSize(); ++i, Rotate(1)) {
+ if(IsNeighborCellOccupied()) {
+ neighbors.insert(GetNeighbor()->GetID());
+ }
+ }
+ return neighbors;
+}
+
+
+void cOrganism::LoadNeighborhood() {
+ InitNeighborhood();
+ m_neighborhood->neighbors = GetNeighborhood();
+ m_neighborhood->loaded = true;
+}
+
+
+bool cOrganism::HasNeighborhoodChanged() {
+ InitNeighborhood();
+ // Must have loaded the neighborhood first:
+ if(!m_neighborhood->loaded) return false;
+
+ // Ok, get the symmetric difference between the old neighborhood and the current neighborhood:
+ Neighborhood symdiff;
+ Neighborhood current = GetNeighborhood();
+ std::set_symmetric_difference(m_neighborhood->neighbors.begin(),
+ m_neighborhood->neighbors.end(),
+ current.begin(),
+ current.end(),
+ std::insert_iterator<Neighborhood>(symdiff, symdiff.begin()));
+
+ // If the symmetric difference is empty, then nothing has changed -- return
+ return !symdiff.empty();
+}
Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cOrganism.h 2009-02-20 16:10:36 UTC (rev 3151)
@@ -26,10 +26,11 @@
#ifndef cOrganism_h
#define cOrganism_h
+#include <deque>
#include <iostream>
+#include <set>
#include <string>
#include <vector>
-#include <deque>
#ifndef cCPUMemory_h
#include "cCPUMemory.h"
@@ -384,7 +385,8 @@
//! Called when this organism attempts to send a message.
bool SendMessage(cAvidaContext& ctx, cOrgMessage& msg);
- bool BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg);
+ //! Called when this organism attempts to broadcast a message.
+ bool BroadcastMessage(cAvidaContext& ctx, cOrgMessage& msg, int depth);
//! Called when this organism has been sent a message.
void ReceiveMessage(cOrgMessage& msg);
//! Called when this organism attempts to move a received message into its CPU.
@@ -393,7 +395,9 @@
const message_list_type& GetReceivedMessages() { InitMessaging(); return m_msg->received; }
//! Returns the list of all messages sent by this organism.
const message_list_type& GetSentMessages() { InitMessaging(); return m_msg->sent; }
-
+ //! Use at your own rish; clear all the message buffers.
+ void FlushMessageBuffers() { InitMessaging(); m_msg->sent.clear(); m_msg->received.clear(); }
+
private:
/*! Contains all the different data structures needed to support messaging within
cOrganism. Inspired by cNetSupport (above), the idea is to minimize impact on
@@ -487,6 +491,27 @@
void SendFlash(cAvidaContext& ctx);
// -------- End of synchronization support --------
+
+ // -------- Neighborhood support --------
+public:
+ typedef std::set<int> Neighborhood; //!< Typedef for a neighborhood snapshot.
+ //! Get the current neighborhood.
+ Neighborhood GetNeighborhood();
+ //! Loads this organism's current neighborhood into memory.
+ void LoadNeighborhood();
+ //! Has the current neighborhood changed from what is in memory?
+ bool HasNeighborhoodChanged();
+
+protected:
+ //! Initialize neighborhood support.
+ inline void InitNeighborhood() { if(!m_neighborhood) { m_neighborhood = new cNeighborhoodSupport(); } }
+ //! Container for neighborhood support.
+ struct cNeighborhoodSupport {
+ cNeighborhoodSupport() : loaded(false) { }
+ bool loaded;
+ Neighborhood neighbors;
+ };
+ cNeighborhoodSupport* m_neighborhood; //!< Lazily-initialized pointer to the neighborhood data.
// -------- Internal Support Methods --------
Modified: development/source/main/cPopulationCell.cc
===================================================================
--- development/source/main/cPopulationCell.cc 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cPopulationCell.cc 2009-02-20 16:10:36 UTC (rev 3151)
@@ -116,6 +116,26 @@
}
}
+/*! This method recursively builds a set of cells that neighbor this cell, out to
+ the given depth. The set must be passed in by-reference, as calls to this method
+ must share a common set of already-visited cells.
+ */
+void cPopulationCell::GetNeighboringCells(std::set<cPopulationCell*>& cell_set, int depth) const {
+ typedef std::set<cPopulationCell*> cell_set_t;
+
+ // For each cell in our connection list...
+ tConstListIterator<cPopulationCell> i(m_connections);
+ while(!i.AtEnd()) {
+ // store the cell pointer, and check to see if we've already visited that cell...
+ cPopulationCell* cell = i.Next();
+ std::pair<cell_set_t::iterator, bool> ins = cell_set.insert(cell);
+ // and if so, recurse to it...
+ if(ins.second && (depth > 1)) {
+ cell->GetNeighboringCells(cell_set, depth-1);
+ }
+ }
+}
+
/*! These values are chosen so as to make loops on the facing 'easy'.
111 = NE
101 = E
Modified: development/source/main/cPopulationCell.h
===================================================================
--- development/source/main/cPopulationCell.h 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cPopulationCell.h 2009-02-20 16:10:36 UTC (rev 3151)
@@ -27,6 +27,7 @@
#define cPopulationCell_h
#include <fstream>
+#include <set>
#ifndef cMutationRates_h
#include "cMutationRates.h"
@@ -95,6 +96,8 @@
inline cOrganism* GetOrganism() const { return m_organism; }
inline cHardwareBase* GetHardware() const { return m_hardware; }
inline tList<cPopulationCell>& ConnectionList() { return m_connections; }
+ //! Recursively build a set of cells that neighbor this one, out to the given depth.
+ void GetNeighboringCells(std::set<cPopulationCell*>& cell_set, int depth) const;
inline cPopulationCell& GetCellFaced() { return *(m_connections.GetFirst()); }
int GetFacing(); // Returns the facing of this cell.
inline void GetPosition(int& x, int& y) { x = m_x; y = m_y; } // Retrieves the position (x,y) coordinates of this cell.
Modified: development/source/main/cPopulationInterface.cc
===================================================================
--- development/source/main/cPopulationInterface.cc 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cPopulationInterface.cc 2009-02-20 16:10:36 UTC (rev 3151)
@@ -287,42 +287,30 @@
return true;
}
-/* Send a message to the given organism */
-bool cPopulationInterface::SendMessage(cOrganism* recvr, cOrgMessage& msg) {
- assert(recvr != NULL);
- recvr->ReceiveMessage(msg);
- return true;
-} //End SendMessage()
+/*! Send a message to the faced organism, failing if this cell does not have
+ neighbors or if the cell currently faced is not occupied. */
+bool cPopulationInterface::BroadcastMessage(cOrgMessage& msg, int depth) {
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(m_cell_id);
+ assert(cell.IsOccupied()); // This organism; sanity.
+
+ // Get the set of cells that are within range.
+ std::set<cPopulationCell*> cell_set;
+ cell.GetNeighboringCells(cell_set, depth);
+
+ // Remove this cell from the set!
+ cell_set.erase(&cell);
+
+ // Now, send a message to each organism living in that set of cells.
+ for(std::set<cPopulationCell*>::iterator i=cell_set.begin(); i!=cell_set.end(); ++i) {
+ if((*i)->IsOccupied()) {
+ (*i)->GetOrganism()->ReceiveMessage(msg);
+ }
+ }
+ return true;
+}
-// Broadcast the message to all living organisms within range
-bool cPopulationInterface::BroadcastMessage(cOrgMessage& msg) {
- bool all_sent = true;
- const int bcast_range = m_world->GetConfig().MESSAGE_BCAST_RADIUS.Get();
- assert(bcast_range >= 0);
- tVector<int> neighbors;
- neighbors.Clear();
-
- cDeme& deme = m_world->GetPopulation().GetDeme(GetDemeID());
- deme.GetSurroundingCellIds(neighbors, GetCellID(), bcast_range);
-
- for(int i = 0; i < neighbors.Size(); i++) {
- cPopulationCell& rcell = m_world->GetPopulation().GetCell(neighbors[i]);
- if(rcell.IsOccupied()) {
- cOrganism* neighbor = rcell.GetOrganism();
- assert(neighbor != NULL);
-
- if(!SendMessage(neighbor, msg)) {
- all_sent = false;
- }
- }
- }
-
- return all_sent;
-
-} //End BroadcastMessage
-
bool cPopulationInterface::BcastAlarm(int jump_label, int bcast_range) {
bool successfully_sent(false);
cPopulationCell& scell = m_world->GetPopulation().GetCell(m_cell_id);
Modified: development/source/main/cPopulationInterface.h
===================================================================
--- development/source/main/cPopulationInterface.h 2009-02-19 16:19:24 UTC (rev 3150)
+++ development/source/main/cPopulationInterface.h 2009-02-20 16:10:36 UTC (rev 3151)
@@ -107,7 +107,7 @@
//! Send a message to the faced organism.
bool SendMessage(cOrgMessage& msg);
bool SendMessage(cOrganism* recvr, cOrgMessage& msg);
- bool BroadcastMessage(cOrgMessage& msg);
+ bool BroadcastMessage(cOrgMessage& msg, int depth);
bool BcastAlarm(int jump_label, int bcast_range);
void DivideOrgTestamentAmongDeme(double value);
//! Send a flash to all neighboring organisms.
More information about the Avida-cvs
mailing list