[Avida-SVN] r3239 - in development/source: actions cpu main tools viewer-core
hjg at myxo.css.msu.edu
hjg at myxo.css.msu.edu
Mon May 18 13:15:08 PDT 2009
Author: hjg
Date: 2009-05-18 16:15:08 -0400 (Mon, 18 May 2009)
New Revision: 3239
Modified:
development/source/actions/PrintActions.cc
development/source/cpu/cHardwareCPU.cc
development/source/cpu/cHardwareCPU.h
development/source/cpu/cTestCPU.h
development/source/cpu/cTestCPUInterface.h
development/source/main/cAvidaConfig.h
development/source/main/cEnvironment.h
development/source/main/cOrgInterface.h
development/source/main/cOrganism.cc
development/source/main/cOrganism.h
development/source/main/cPopulationInterface.cc
development/source/main/cPopulationInterface.h
development/source/main/cStats.cc
development/source/main/cStats.h
development/source/main/cTaskLib.cc
development/source/main/cTaskLib.h
development/source/tools/cString.h
development/source/viewer-core/cCoreView_Info.cc
Log:
A set of instructions, tasks, and stats that support reputation-based altruism. Specifically, they support creating and donating different types of strings. A more thorough description of thier uses can be found in Decomposition Using Indirect Reciprocity in Evolved Populations by Heather Goldsby, Sherri Goings, Jeff Clune, and Charles Ofria. Additionally, a new consistency test that makes sure all the reputation infrastructure is working.
Modified: development/source/actions/PrintActions.cc
===================================================================
--- development/source/actions/PrintActions.cc 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/actions/PrintActions.cc 2009-05-18 20:15:08 UTC (rev 3239)
@@ -131,6 +131,10 @@
STATS_OUT_FILE(PrintDynamicMaxMinData, maxmin.dat );
STATS_OUT_FILE(PrintNumOrgsKilledData, orgs_killed.dat);
+// reputation
+STATS_OUT_FILE(PrintReputationData, reputation.dat);
+STATS_OUT_FILE(PrintDirectReciprocityData, reciprocity.dat);
+STATS_OUT_FILE(PrintStringMatchData, stringmatch.dat);
#define POP_OUT_FILE(METHOD, DEFAULT) /* 1 */ \
class cAction ## METHOD : public cAction { /* 2 */ \
@@ -3136,6 +3140,11 @@
action_lib->Register<cActionDumpTaskGrid>("dump_task_grid");
action_lib->Register<cActionDumpDonorGrid>("dump_donor_grid");
action_lib->Register<cActionDumpReceiverGrid>("dump_receiver_grid");
+
+ // Reputation
+ action_lib->Register<cActionPrintReputationData>("PrintReputationData");
+ action_lib->Register<cActionPrintDirectReciprocityData>("PrintDirectReciprocityData");
+ action_lib->Register<cActionPrintStringMatchData>("PrintStringMatchData");
action_lib->Register<cActionSetVerbose>("VERBOSE");
}
Modified: development/source/cpu/cHardwareCPU.cc
===================================================================
--- development/source/cpu/cHardwareCPU.cc 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/cpu/cHardwareCPU.cc 2009-05-18 20:15:08 UTC (rev 3239)
@@ -542,6 +542,29 @@
tInstLibEntry<tMethod>("get-neighborhood", &cHardwareCPU::Inst_GetNeighborhood, nInstFlag::STALL),
tInstLibEntry<tMethod>("if-neighborhood-changed", &cHardwareCPU::Inst_IfNeighborhoodChanged, nInstFlag::STALL),
+
+ // Reputation instructions
+
+ tInstLibEntry<tMethod>("donate-frm", &cHardwareCPU::Inst_DonateFacingRawMaterials, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("donate-spec", &cHardwareCPU::Inst_DonateFacingRawMaterialsOtherSpecies, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("donate-if-donor", &cHardwareCPU::Inst_DonateIfDonor, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("donate-string", &cHardwareCPU::Inst_DonateFacingString, nInstFlag::STALL),
+
+ tInstLibEntry<tMethod>("get-neighbors-reputation", &cHardwareCPU::Inst_GetNeighborsReputation, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("get-reputation", &cHardwareCPU::Inst_GetReputation, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("get-raw-mat-amount", &cHardwareCPU::Inst_GetAmountOfRawMaterials, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("get-other-raw-mat-amount", &cHardwareCPU::Inst_GetAmountOfOtherRawMaterials, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("pose", &cHardwareCPU::Inst_Pose, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("rotate-to-rep", &cHardwareCPU::Inst_RotateToGreatestReputation, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("rotate-to-rep-and-donate", &cHardwareCPU::Inst_RotateToGreatestReputationAndDonate, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("rotate-to-rep-tag", &cHardwareCPU::Inst_RotateToGreatestReputationWithDifferentTag, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("rotate-to-rep-lineage", &cHardwareCPU::Inst_RotateToGreatestReputationWithDifferentLineage, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("rotate-to-tag", &cHardwareCPU::Inst_RotateToDifferentTag, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("if-donor", &cHardwareCPU::Inst_IfDonor, nInstFlag::STALL),
+ tInstLibEntry<tMethod>("prod-string", &cHardwareCPU::Inst_ProduceString, nInstFlag::STALL),
+
+
+
// Must always be the last instruction in the array
tInstLibEntry<tMethod>("NULL", &cHardwareCPU::Inst_Nop, 0, "True no-operation instruction: does nothing"),
};
@@ -8247,3 +8270,378 @@
bool cHardwareCPU::Inst_Broadcast8(cAvidaContext& ctx) {
return BroadcastX(ctx, 8);
}
+
+
+
+/* Donate if the neighbor previously donated to the organism. */
+bool cHardwareCPU::Inst_DonateIfDonor(cAvidaContext& ctx)
+{
+ cOrganism * neighbor = m_organism->GetNeighbor();
+ if (neighbor != NULL) {
+ // check if the neighbor was a donor
+ if (m_organism->IsDonor(neighbor->GetID())) {
+ m_world->GetStats().IncDonateToDonor();
+ Inst_DonateFacingRawMaterialsOtherSpecies(ctx);
+ }
+ }
+ return true;
+}
+
+/* Donate raw materials (of one kind) to a neighbor, but
+ only if the neighbor is of a different species. If the
+ instruction fails, there is no consequence. */
+bool cHardwareCPU::Inst_DonateFacingRawMaterialsOtherSpecies(cAvidaContext& ctx)
+{
+ cOrganism * neighbor = m_organism->GetNeighbor();
+ if (neighbor != NULL) {
+
+ int spec_self = m_organism->GetLineageLabel();
+ int spec_neighbor = neighbor->GetLineageLabel();
+
+ if (spec_self != spec_neighbor) {
+ Inst_DonateFacingString(ctx);
+ }
+ }
+ return true;
+}
+
+/* Donate a string that you have produced to the facing organism */
+bool cHardwareCPU::Inst_DonateFacingString(cAvidaContext& ctx)
+{
+ // Get faced neighbor
+ cOrganism * neighbor = m_organism->GetNeighbor();
+ int cost = m_world->GetConfig().ALT_COST.Get();
+ int my_string = m_organism->GetLineageLabel();
+
+
+ // Donate only if we have found a neighbor.
+ if (neighbor != NULL) {
+
+ // Check if the organism has enough of this string on hand.
+ if ((m_organism->GetNumberStringsOnHand(my_string) >= cost) && (neighbor->CanReceiveString(my_string, cost))) {
+
+ // sometimes the donation will fail.
+ // get the probability of failure
+ int prob_fail = m_world->GetConfig().DONATION_FAILURE_PERCENT.Get();
+ unsigned int rand_num = m_world->GetRandom().GetUInt(0, 100);
+ // neighbor donates to organism.
+ if (rand_num < prob_fail) {
+ // EXIT
+ return true;
+ }
+
+
+ m_organism->DonateString(my_string, cost);
+ neighbor->AddOtherRawMaterials(cost, m_organism->GetID());
+ neighbor->ReceiveString(my_string, cost, m_organism->GetID());
+ neighbor->AddDonatedLineage(m_organism->GetLineageLabel());
+
+ // track stats
+ m_organism->Donated();
+
+ ComputeReputation();
+ }
+ }
+ return true;
+
+
+}
+
+/* Donate raw materials to the facing organism. */
+bool cHardwareCPU::Inst_DonateFacingRawMaterials(cAvidaContext& ctx)
+{
+
+ // Get faced neighbor
+ cOrganism * neighbor = m_organism->GetNeighbor();
+ int cost = m_world->GetConfig().ALT_COST.Get();
+
+
+ // Donate only if we have found a neighbor.
+ if (neighbor != NULL) {
+
+ // Subtract raw materials from the organism (currently subtracts 1 resource...)
+ // fails if the organism does not have any more resources
+ if (m_organism->SubtractSelfRawMaterials(cost)) {
+
+ // sometimes the donation will fail.
+ // get the probability of failure
+ int prob_fail = m_world->GetConfig().DONATION_FAILURE_PERCENT.Get();
+ unsigned int rand_num = m_world->GetRandom().GetUInt(0, 100);
+ // neighbor donates to organism.
+ if (rand_num < prob_fail) {
+ // EXIT
+ return true;
+ }
+
+
+ neighbor->AddOtherRawMaterials(cost, m_organism->GetID());
+ neighbor->AddDonatedLineage(m_organism->GetLineageLabel());
+
+ // rotate recipient to face donor
+ // by rotating until the recipient faces the donor
+ // adding a new comment.
+ if (m_world->GetConfig().ROTATE_ON_DONATE.Get()) {
+ while (neighbor->GetNeighbor() != m_organism) {
+ neighbor->Rotate(1);
+ }
+ }
+
+
+ // track stats
+ m_organism->Donated();
+
+ ComputeReputation();
+
+ }
+ }
+ return true;
+}
+
+
+
+
+/* An organism artificially increases its reputation without donating. */
+bool cHardwareCPU::Inst_Pose(cAvidaContext& ctx)
+{
+ // update reputation to include this phony donation.
+ // get the current reputation; increment by 1.
+ m_organism->SetReputation(m_organism->GetReputation() + 1);
+
+ return true;
+}
+
+
+
+/*! An organism's reputation is stored as an opinion. This instruction
+ uses Inst_GetNeighborsOpinion to do the heavy lifting, but includes
+ default behavior suitable for reputations. Specifically, if an
+ neighbor has no reputation (i.e., it has not donated) or does not
+ exist, then this instruction puts zeros into the registers.
+ */
+bool cHardwareCPU::Inst_GetNeighborsReputation(cAvidaContext& ctx)
+{
+ // Get faced neighbor
+ cOrganism * neighbor = m_organism->GetNeighbor();
+ if (neighbor != NULL) {
+ const int raw_mat_reg = FindModifiedRegister(REG_AX);
+ GetRegister(raw_mat_reg) = neighbor->GetReputation();
+ }
+ return true;
+}
+
+
+/*! An organism's reputation is stored as an opinion. This instruction
+ uses Inst_GetOpinion to do the heavy lifting, but includes
+ default behavior suitable for reputations. Specifically, if an
+ organism has no reputation (i.e., it has not donated), then this
+ instruction puts zeros into the registers.
+ */
+bool cHardwareCPU::Inst_GetReputation(cAvidaContext& ctx)
+{
+ const int opinion_reg = FindModifiedRegister(REG_BX);
+ GetRegister(opinion_reg) = m_organism->GetReputation();
+ return true;
+}
+
+/* Sense the number of raw materials an organism has. Store in
+ ?REG_AX? */
+bool cHardwareCPU::Inst_GetAmountOfRawMaterials(cAvidaContext& ctx)
+{
+ const int raw_mat_reg = FindModifiedRegister(REG_AX);
+ GetRegister(raw_mat_reg) = m_organism->GetNumberStringsOnHand(0);
+ return true;
+}
+
+/* Sense the number of raw materials an organism has. Store in
+ ?REG_BX? */
+bool cHardwareCPU::Inst_GetAmountOfOtherRawMaterials(cAvidaContext& ctx)
+{
+ const int raw_mat_reg = FindModifiedRegister(REG_BX);
+ GetRegister(raw_mat_reg) = m_organism->GetNumberStringsOnHand(1);
+ return true;
+}
+
+
+
+/* Rotate to face the organism with the highest reputation */
+bool cHardwareCPU::Inst_RotateToGreatestReputation(cAvidaContext& ctx)
+{
+ m_organism->GetOrgInterface().RotateToGreatestReputation();
+
+ return true;
+}
+
+/* Rotate to face the organism with the highest reputation that has
+ a different tag. */
+bool cHardwareCPU::Inst_RotateToGreatestReputationWithDifferentTag(cAvidaContext& ctx)
+{
+ m_organism->GetOrgInterface().RotateToGreatestReputationWithDifferentTag(m_organism->GetTagLabel());
+ return true;
+}
+
+/* Rotate to face the organism with the highest reputation that has
+ a different lineage. */
+bool cHardwareCPU::Inst_RotateToGreatestReputationWithDifferentLineage(cAvidaContext& ctx)
+{
+ m_organism->GetOrgInterface().RotateToGreatestReputationWithDifferentLineage(m_organism->GetLineageLabel());
+ return true;
+}
+
+
+/* Rotate to face the organism with the highest reputation and then
+ immediately donate */
+bool cHardwareCPU::Inst_RotateToGreatestReputationAndDonate(cAvidaContext& ctx)
+{
+ Inst_RotateToGreatestReputation(ctx);
+ Inst_DonateFacingRawMaterials(ctx);
+ return true;
+}
+
+
+
+
+bool cHardwareCPU::Inst_RotateToDifferentTag(cAvidaContext& ctx)
+{
+ //get the neighborhood size
+ const int num_neighbors = m_organism->GetNeighborhoodSize();
+
+ // Turn to face a random neighbor
+ int neighbor_id = ctx.GetRandom().GetInt(num_neighbors);
+ for (int i = 0; i < neighbor_id; i++) m_organism->Rotate(1);
+ cOrganism * neighbor = m_organism->GetNeighbor();
+
+ int max_id = neighbor_id + num_neighbors;
+
+ //we have not found a match yet
+ bool found = false;
+
+ // rotate through orgs in neighborhood
+ while (neighbor_id < max_id) {
+ neighbor = m_organism->GetNeighbor();
+
+ //if neighbor exists, do they have a different tag?
+ if (neighbor != NULL) {
+ if (m_organism->GetTagLabel() != neighbor->GetTagLabel()) found = true;
+
+ }
+
+ // stop searching through the neighbors if we already found one
+ if (found == true){
+ break;
+ }
+
+ m_organism->Rotate(1);
+ neighbor_id++;
+ }
+
+ return true;
+}
+
+
+
+
+/* Execute the next instruction if the neighbor was a donor. */
+bool cHardwareCPU::Inst_IfDonor(cAvidaContext& ctx)
+{
+ bool donor = false;
+ cOrganism * neighbor = m_organism->GetNeighbor();
+ if (neighbor != NULL) {
+ // check if the neighbor was a donor
+ if (m_organism->IsDonor(neighbor->GetID())) {
+ donor = true;
+ }
+ }
+ if (!donor) IP().Advance();
+
+ return true;
+
+}
+
+
+void cHardwareCPU::ComputeReputation()
+{
+ cOrganism * neighbor = m_organism->GetNeighbor();
+
+ // update reputation to include this donation.
+ // get the current reputation; increment by 1.
+ // includes a concept of standing
+ if (m_world->GetConfig().AUTO_REPUTATION.Get() == 1) {
+ int my_rep = m_organism->GetReputation();
+ m_organism->SetReputation(my_rep +1);
+ // get neighbor reputation
+ int rep = neighbor->GetReputation();
+ // if the organism has not yet donated, put it into bad standing
+ if (rep == 0) neighbor->SetReputation(-1);
+ } else if (m_world->GetConfig().AUTO_REPUTATION.Get() == 2) {
+ // reputation is proportional to how much you have donated/received
+ int my_rep = m_organism->GetReputation();
+ m_organism->SetReputation(my_rep +1);
+ // get neighbor reputation
+ int rep = neighbor->GetReputation();
+ neighbor->SetReputation(rep-1);
+ } else if (m_world->GetConfig().AUTO_REPUTATION.Get() == 3) {
+ // set rep to 1, since the organism donated
+ m_organism->SetReputation(1);
+ // get neighbor reputation
+ int rep = neighbor->GetReputation();
+ // if the organism has not yet donated, put it into bad standing
+ if (rep == 0) neighbor->SetReputation(-1);
+ } else if (m_world->GetConfig().AUTO_REPUTATION.Get() == 4) {
+ // Similar to 1, except does not include standing.
+ int my_rep = m_organism->GetReputation();
+ m_organism->SetReputation(my_rep +1);
+ }
+
+}
+
+
+
+
+/* Check if the string in the organisms buffer corresponds to the
+ string it is producing. If so, -1 out the buffer and increment the
+ number of raw materials the organism has. Otherwise, do nothing. */
+bool cHardwareCPU::Inst_ProduceString(cAvidaContext& ctx)
+{
+
+ int num = 0;
+ int max_num = 0;
+ int max_string = -1;
+ int string_size = 0;
+ bool val;
+
+ m_organism->InitStringMap();
+
+ // Figure out if it has produced any of the strings
+ std::vector < cString > temp_strings = m_world->GetEnvironment().GetMatchStringsFromTask();
+ if (temp_strings.size()) string_size = temp_strings[0].GetSize();
+ for (unsigned int i=0; i < temp_strings.size(); i++){
+ num = m_organism->MatchOutputBuffer(temp_strings[i]);
+ if (num > max_num) {
+ max_num = num;
+ max_string = i;
+ }
+ }
+
+ // Determine if it has to produce one in particular.
+ if (m_world->GetConfig().SPECIALISTS.Get()) {
+ if (m_organism->GetLineageLabel() != max_string) {
+ max_num = 0;
+ }
+ }
+
+
+ // If still ok, add the raw material and clear the buffer
+ if (max_num == string_size) {
+ // Indicate organism has produced the string
+ val = m_organism->ProduceString(max_string);
+
+ // temp until old code is phased out:
+ m_organism->AddSelfRawMaterials(1);
+
+ // Clear buffer if the organism has received credit for the string
+ if (val) m_organism->SetOutputNegative1();
+ }
+
+ return true;
+}
+
Modified: development/source/cpu/cHardwareCPU.h
===================================================================
--- development/source/cpu/cHardwareCPU.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/cpu/cHardwareCPU.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -704,6 +704,54 @@
bool Inst_Alarm_MSG_Bit_Cons24_multihop(cAvidaContext& ctx);
bool Inst_Alarm_Label(cAvidaContext& ctx);
bool Jump_To_Alarm_Label(int jump_label);
+
+
+ // -------- Reputation support --------
+ /* These instructions interact with the "reputation" support in cOrganism.h. They
+ are based on the donate instructions. However, these instructions donate
+ "raw materials" rather than merit and will eventually be used to support
+ reputation based cooperation.
+ */
+ // Donate a raw material to the neighbor
+ bool Inst_DonateFacingRawMaterials(cAvidaContext& ctx);
+ // Donate a raw material to the neighbor if it is another species
+ bool Inst_DonateFacingRawMaterialsOtherSpecies(cAvidaContext& ctx);
+ // Donate a raw material to the neighbor if it was a prior donor
+ bool Inst_DonateIfDonor(cAvidaContext& ctx);
+ // Donate a string to the neighbor, if it's reputation is > 0
+ bool Inst_DonateStringIfDonorRep(cAvidaContext& ctx);
+ // Donate a string to a neighbor
+ bool Inst_DonateFacingString(cAvidaContext& ctx);
+
+ // Rotate to the organims with the greatest reputation
+ bool Inst_RotateToGreatestReputation(cAvidaContext& ctx);
+ // Rotate to the organims with the greatest reputation that has a different tag
+ bool Inst_RotateToGreatestReputationWithDifferentTag(cAvidaContext& ctx);
+ // Rotate to the organims with the greatest reputation that has a different tag
+ bool Inst_RotateToGreatestReputationWithDifferentLineage(cAvidaContext& ctx);
+ // Rotate to an organim with a different tag
+ bool Inst_RotateToDifferentTag(cAvidaContext& ctx);
+ // Rotate to the organims with the greatest reputation and donate
+ bool Inst_RotateToGreatestReputationAndDonate(cAvidaContext& ctx);
+ // Get a neighbor's reputation
+ bool Inst_GetNeighborsReputation(cAvidaContext& ctx);
+ // Get the organism's reputation
+ bool Inst_GetReputation(cAvidaContext& ctx);
+ // Execute the following instruction if the facing neighbor was a donor
+ bool Inst_IfDonor(cAvidaContext& ctx);
+ // Produce string
+ bool Inst_ProduceString(cAvidaContext& ctx);
+ // Get the organism's raw material level
+ bool Inst_GetAmountOfRawMaterials(cAvidaContext& ctx);
+ // Get the number of raw materials the organism
+ // has gotten from others
+ bool Inst_GetAmountOfOtherRawMaterials(cAvidaContext& ctx);
+ // Pretend to donate
+ bool Inst_Pose(cAvidaContext& ctx);
+
+ // Reputation
+ void ComputeReputation();
+
//// Placebo ////
bool Inst_Skip(cAvidaContext& ctx);
@@ -794,6 +842,8 @@
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/cTestCPU.h
===================================================================
--- development/source/cpu/cTestCPU.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/cpu/cTestCPU.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -116,6 +116,8 @@
// Used by cTestCPUInterface to get/update resources
void ModifyResources(const tArray<double>& res_change);
cResourceCount& GetResourceCount() { return m_resource_count; }
+
+
};
#ifdef ENABLE_UNIT_TESTS
Modified: development/source/cpu/cTestCPUInterface.h
===================================================================
--- development/source/cpu/cTestCPUInterface.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/cpu/cTestCPUInterface.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -97,6 +97,10 @@
bool BcastAlarm(int jump_label, int bcast_range) { return false; }
void DivideOrgTestamentAmongDeme(double value) {;}
void SendFlash() { }
+
+ void RotateToGreatestReputation(){ }
+ void RotateToGreatestReputationWithDifferentTag(int tag){ }
+ void RotateToGreatestReputationWithDifferentLineage(int tag){ }
int GetStateGridID(cAvidaContext& ctx);
};
Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cAvidaConfig.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -619,6 +619,23 @@
CONFIG_ADD_CUSTOM_FORMAT(INST_SET_NEW, "Instruction Set Definition");
CONFIG_ADD_FORMAT_VAR(INST, "Instruction entry in the instruction set");
+
+
+ //--------- Reputation config options --------------
+ CONFIG_ADD_CUSTOM_FORMAT(REPUTATION_GROUP, "Reputation Settings");
+ CONFIG_ADD_VAR(RAW_MATERIAL_AMOUNT, int, 100, "Number of raw materials an organism starts with");
+ CONFIG_ADD_VAR(AUTO_REPUTATION, int, 0, "Is an organism's reputation automatically computed based on its donations\n0=no\n1=increment for each donation + standing\n2=+1 for donations given -1 for donations received\n3=1 for donors -1 for recivers who have not donated\n4=+1 for donors\n5=+1 for donors during task check");
+ CONFIG_ADD_VAR(ALT_BENEFIT, int, 1.00, "Number multiplied by the number of raw materials received from another organism to compute reward");
+ CONFIG_ADD_VAR(ALT_COST, int, 1.00, "Number multiplied by the number of your raw materials");
+ CONFIG_ADD_VAR(ROTATE_ON_DONATE, int, 0, "Rotate an organism to face its donor 0/1 (off/on)");
+ CONFIG_ADD_VAR(REPUTATION_REWARD, int, 0, "Reward an organism for having a good reputation");
+ CONFIG_ADD_VAR(DONATION_FAILURE_PERCENT, int, 0, "Percentage of times that a donation fails");
+ CONFIG_ADD_VAR(RANDOMIZE_RAW_MATERIAL_AMOUNT, int, 0, "Should all the organisms receive the same amount 0/1 (off/on)");
+ CONFIG_ADD_VAR(DONATION_RESTRICTIONS, int, 0, "0=none\n1=inter-species only\n2=different tag only");
+ CONFIG_ADD_VAR(INHERIT_REPUTATION, int, 0, "0=reputations are not inherited\n1=reputations are inherited\n2=tags are inherited");
+ CONFIG_ADD_VAR(SPECIALISTS, int, 0, "0=generalists allowed\n1=only specialists");
+ CONFIG_ADD_VAR(STRING_AMOUNT_CAP, int, -1, "-1=no cap on string amounts\n#=CAP");
+ CONFIG_ADD_VAR(MATCH_ALREADY_PRODUCED, int, 0, "0=off\n1=on");
#endif
Modified: development/source/main/cEnvironment.h
===================================================================
--- development/source/main/cEnvironment.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cEnvironment.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -156,6 +156,9 @@
const cTaskEntry& GetTask(int id) const { return m_tasklib.GetTask(id); }
bool UseNeighborInput() const { return m_tasklib.UseNeighborInput(); }
bool UseNeighborOutput() const { return m_tasklib.UseNeighborOutput(); }
+ vector<cString> GetMatchStringsFromTask() { return m_tasklib.GetMatchStrings(); }
+ cString GetMatchString(int x) { return m_tasklib.GetMatchString(x); }
+ int GetNumberOfMatchStrings() { return m_tasklib.GetNumberOfMatchStrings(); }
int GetNumReactions() const { return reaction_lib.GetSize(); }
Modified: development/source/main/cOrgInterface.h
===================================================================
--- development/source/main/cOrgInterface.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cOrgInterface.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -110,6 +110,10 @@
virtual void SendFlash() = 0;
virtual int GetStateGridID(cAvidaContext& ctx) = 0;
+ virtual void RotateToGreatestReputation() =0;
+ virtual void RotateToGreatestReputationWithDifferentTag(int tag) =0;
+ virtual void RotateToGreatestReputationWithDifferentLineage(int line) =0;
+
};
#endif
Modified: development/source/main/cOrganism.cc
===================================================================
--- development/source/main/cOrganism.cc 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cOrganism.cc 2009-05-18 20:15:08 UTC (rev 3239)
@@ -1000,3 +1000,212 @@
// If the symmetric difference is empty, then nothing has changed -- return
return !symdiff.empty();
}
+
+
+/* Called when raw materials are donated to others or when the
+ raw materials are consumed. Amount is the number of resources
+ donated. The boolean flag is used to indicate if the donation
+ was successful... It would fail if the organism did not have
+ that many resources. */
+bool cOrganism::SubtractSelfRawMaterials (int amount)
+{
+ bool isSuccessful = false;
+ if (amount <= m_self_raw_materials) {
+ isSuccessful = true;
+ m_self_raw_materials -= amount;
+ }
+ return isSuccessful;
+}
+
+
+/* Called when other raw materials are consumed. Amount is the
+ number of resources consumed. The boolean flag is used to
+ indicate if the donation was successful... It would fail if
+ the organism did not have that many resources. */
+bool cOrganism::SubtractOtherRawMaterials (int amount)
+{
+ bool isSuccessful = false;
+ if (amount <= m_other_raw_materials) {
+ isSuccessful = true;
+ m_other_raw_materials -= amount;
+ }
+ return isSuccessful;
+}
+
+/* Called when raw materials are received from others. Amount
+ is the number of resources received. The boolean flag is used
+ to indicate if the reception was successful, which should always
+ be the case... */
+
+bool cOrganism::AddOtherRawMaterials (int amount, int donor_id) {
+ bool isSuccessful = true;
+ m_other_raw_materials += amount;
+ donor_list.insert(donor_id);
+ m_num_donate_received += amount;
+ m_amount_donate_received++;
+ return isSuccessful;
+}
+
+/* Called when raw materials are received from others. Amount
+ is the number of resources received. The boolean flag is used
+ to indicate if the reception was successful, which should always
+ be the case...
+
+ This version is used if there is only one resource that is both
+ donated and recieved.
+ */
+
+bool cOrganism::AddRawMaterials (int amount, int donor_id) {
+ bool isSuccessful = true;
+ m_self_raw_materials += amount;
+ donor_list.insert(donor_id);
+ m_num_donate_received += amount;
+ m_amount_donate_received++;
+ return isSuccessful;
+}
+
+
+/* Get an organism's reputation, which is expressed as an
+ opinion. 0 is the default reputation (this should be refactored
+ to be cleaner). */
+int cOrganism::GetReputation() {
+ int rep =0;
+ if (HasOpinion()) {
+ rep = GetOpinion().first;
+ }
+ return rep;
+}
+
+/* Set an organism's reputation */
+void cOrganism::SetReputation(int rep) {
+ SetOpinion(rep);
+ return;
+}
+
+/* An organism's reputation is based on a running average*/
+void cOrganism::SetAverageReputation(int rep){
+ int current_total = GetReputation() * m_opinion->opinion_list.size();
+ int new_rep = (current_total + rep)/(m_opinion->opinion_list.size()+1);
+ SetReputation(new_rep);
+}
+
+
+/* Check if an organism has previously donated to this organism */
+bool cOrganism::IsDonor(int neighbor_id)
+{
+ bool found = false;
+ if (donor_list.find(neighbor_id) != donor_list.end()) {
+ found = true;
+ }
+ return found;
+}
+
+
+
+/* Update the tag. If the organism was not already tagged,
+ or the new tag is the same as the old tag, or the number
+ of bits is > than the old tag, update.*/
+void cOrganism::UpdateTag(int new_tag, int bits)
+{
+ unsigned int rand_int = m_world->GetRandom().GetUInt(0, 2);
+ if ((m_tag.first == -1) ||
+ (m_tag.first == new_tag) ||
+ (m_tag.second < bits)) {
+ m_tag = make_pair(new_tag, bits);
+ } else if ((m_tag.second == bits) && rand_int){
+ m_tag = make_pair(new_tag, bits);
+ }
+}
+
+
+/* See if the output buffer matches the string */
+int cOrganism::MatchOutputBuffer(cString string_to_match)
+{
+ tBuffer<int> org_str (GetOutputBuf());
+ int num_matched =0;
+ for (int j = 0; j < string_to_match.GetSize(); j++)
+ {
+ if (string_to_match[j]=='0' && org_str[j]==0 ||
+ string_to_match[j]=='1' && org_str[j]==1)
+ num_matched++;
+ }
+ return num_matched;
+}
+
+
+void cOrganism::SetOutputNegative1()
+{
+ for (int i=0; i<GetOutputBuf().GetCapacity(); i++) {
+ AddOutput(-1);
+ }
+ m_output_buf.Clear();
+}
+
+/* Initialize the string tracking map */
+void cOrganism::InitStringMap()
+{
+ if (!m_string_map.size()) {
+ // Get the strings from the task lib.
+ std::vector < cString > temp_strings = m_world->GetEnvironment().GetMatchStringsFromTask();
+ // Create structure for each of them.
+ for (unsigned int i=0; i < temp_strings.size(); i++){
+ m_string_map[i].m_string = temp_strings[i];
+ }
+ }
+}
+
+
+bool cOrganism::ProduceString(int i)
+{
+ bool val = false;
+ int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get();
+ if ((cap == -1) || (m_string_map[i].on_hand < cap))
+ {
+ m_string_map[i].prod_string++;
+ m_string_map[i].on_hand++;
+ val = true;
+ }
+ return val;
+}
+
+/* Donate a string*/
+bool cOrganism::DonateString(int string_tag, int amount)
+{
+ bool val = false;
+ if (m_string_map[string_tag].on_hand >= amount) {
+ val = true;
+ m_string_map[string_tag].on_hand -= amount;
+ }
+ return val;
+
+}
+
+/* Receive a string*/
+bool cOrganism::ReceiveString(int string_tag, int amount, int donor_id)
+{
+ bool val = false;
+ int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get();
+ if ((cap == -1) || (m_string_map[string_tag].on_hand < cap))
+ {
+ m_string_map[string_tag].received_string++;
+ m_string_map[string_tag].on_hand++;
+ donor_list.insert(donor_id);
+ m_num_donate_received += amount;
+ m_amount_donate_received++;
+ val = true;
+ }
+ return val;
+}
+
+/* Check to see if this amount is below the organism's cap*/
+bool cOrganism::CanReceiveString(int string_tag, int amount)
+{
+ bool val = false;
+ int cap = m_world->GetConfig().STRING_AMOUNT_CAP.Get();
+ if ((cap == -1) || (m_string_map[string_tag].on_hand < cap))
+ {
+ val = true;
+ }
+ return val;
+
+}
Modified: development/source/main/cOrganism.h
===================================================================
--- development/source/main/cOrganism.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cOrganism.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -31,6 +31,7 @@
#include <set>
#include <string>
#include <vector>
+#include <map>
#ifndef cCPUMemory_h
#include "cCPUMemory.h"
@@ -516,6 +517,120 @@
cNeighborhoodSupport* m_neighborhood; //!< Lazily-initialized pointer to the neighborhood data.
+ // -------- Reputation support --------
+public:
+ // Deduct amount number of self raw materials
+ bool SubtractSelfRawMaterials(int amount);
+ // Deduct amount number of other raw materials
+ bool SubtractOtherRawMaterials(int amount);
+ // receive raw materials from others
+ bool AddOtherRawMaterials(int amount, int donor_id);
+ // receive raw materials
+ bool AddRawMaterials(int amount, int donor_id);
+ // receive raw materials
+ void AddSelfRawMaterials(int amount) { if (m_self_raw_materials < 10) m_self_raw_materials += amount;}
+ // retrieve the organism's own amount of raw materials
+ int GetSelfRawMaterials() { return m_self_raw_materials; }
+ // retrieve the amount of raw materials collected from others
+ int GetOtherRawMaterials() { return m_other_raw_materials; }
+ // get the organism's reputation
+ int GetReputation();
+ // set the organism's reputation
+ void SetReputation(int rep);
+ // update the reputation to be an average on the basis of this new info
+ void SetAverageReputation(int rep);
+ // update the reputation by addint this new information
+ void AddReputation(int rep) { SetReputation(GetReputation() + rep); }
+ // increment reputation
+ void IncReputation() { SetReputation(GetReputation() + 1); }
+ // get number of donors
+ int GetNumberOfDonors() { return donor_list.size(); }
+ // organism donated
+ void Donated(){m_num_donate++;}
+ // get number of donations
+ int GetNumberOfDonations() { return m_num_donate; }
+ // get number of donations received
+ int GetNumberOfDonationsReceived() { return m_num_donate_received; }
+ // get amout of donations received
+ int GetAmountOfDonationsReceived() { return m_amount_donate_received; }
+ // organism reciprocated
+ void Reciprocated() {m_num_reciprocate++;}
+ // get number of reciprocations
+ int GetNumberOfReciprocations() { return m_num_reciprocate; }
+ // was the organism a donor
+ bool IsDonor(int neighbor_id);
+
+ // Check if buffer contains this string; return # bits correct
+ int MatchOutputBuffer(cString string_to_match);
+
+ // Add a donor
+ void AddDonor(int org_id) { donor_list.insert(org_id); }
+ // Set tag
+ void SetTag(int new_tag, int bits) { m_tag = make_pair(new_tag, bits); }
+ // Set tag
+ void SetTag(pair < int, int > new_tag) { m_tag = new_tag; }
+ // Update tag
+ void UpdateTag(int new_tag, int bits);
+ // Get tag
+ int GetTagLabel() { return m_tag.first; }
+ pair < int, int > GetTag() { return m_tag; }
+ // Get number of failed reputation increases
+ int GetFailedReputationIncreases() { return m_failed_reputation_increases; }
+
+ // Clear the output buffer
+ void SetOutputNegative1();
+ void AddDonatedLineage(int lin) { donating_lineages.insert(lin); }
+ int GetNumberOfDonatedLineages() { return donating_lineages.size(); }
+ void InitStringMap();
+ bool ProduceString(int i);
+ int GetNumberStringsProduced(int i) { return m_string_map[i].prod_string; }
+ int GetNumberStringsOnHand(int i) { return m_string_map[i].on_hand; }
+ bool DonateString(int string_tag, int amount);
+ bool ReceiveString(int string_tag, int amount, int donor_id);
+ bool CanReceiveString(int string_tag, int amount);
+
+protected:
+ // The organism's own raw materials
+ int m_self_raw_materials;
+ // The raw materials an oranism has collected from others
+ int m_other_raw_materials;
+ // Organisms that have donated to this organism
+ set<int> donor_list;
+ // Strings this organism has received.
+ set<int> donating_lineages;
+ // number of donations
+ int m_num_donate;
+ // number of donations received
+ int m_num_donate_received;
+ // amount of donations received
+ int m_amount_donate_received;
+ // number of reciprocations
+ int m_num_reciprocate;
+ // reputation minimum for donation/rotation
+ // based on Nowak89
+ int m_k;
+ // int number of reputation increase failures
+ int m_failed_reputation_increases;
+ std::pair < int, int > m_tag;
+
+ /*! Contains all the different data structures needed to
+ track strings, production of strings, and donation/trade
+ of strings. It is inspired by the cMessagingSupport*/
+ struct cStringSupport
+ {
+ cStringSupport()
+ { prod_string = 0; received_string = 0; on_hand = 0; }
+ cString m_string; //!< The string being tracked
+ int prod_string; //!< The number of times this string has been produced.
+ int received_string; //!< The number of times this string has been received.
+ int on_hand; //!< The number of copies of the string this organism has on hand
+ };
+
+ /* This member variable is a map of tags to strings. It can
+ be used to track production, consumption, and donation of
+ strings. */
+ std::map < int, cStringSupport > m_string_map;
+
// -------- Internal Support Methods --------
private:
void initialize(cAvidaContext& ctx);
Modified: development/source/main/cPopulationInterface.cc
===================================================================
--- development/source/main/cPopulationInterface.cc 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cPopulationInterface.cc 2009-05-18 20:15:08 UTC (rev 3239)
@@ -400,3 +400,177 @@
{
return ctx.GetRandom().GetUInt(m_world->GetEnvironment().GetNumStateGrids());
}
+
+/* Rotate an organism to face the neighbor with the highest reputation */
+void cPopulationInterface::RotateToGreatestReputation()
+{
+
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
+ int high_rep=-1;
+ vector <int> high_rep_orgs;
+
+
+ // loop to find the max reputation
+ for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+ const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+ // cell->organism, if occupied, check reputation, etc.
+ if (IsNeighborCellOccupied()) {
+ cOrganism* cur_neighbor = faced_cell->GetOrganism();
+
+ // if it has high reputation
+ if (cur_neighbor->GetReputation() >= high_rep) {
+ if (cur_neighbor->GetReputation() > high_rep) {
+ high_rep = cur_neighbor->GetReputation();
+ high_rep_orgs.clear();
+ }
+ high_rep_orgs.push_back(cur_neighbor->GetID());
+ }
+ }
+
+ // check the next neighbor
+ cell.ConnectionList().CircNext();
+ }
+
+ // Pick an organism to donate to
+
+ if (high_rep_orgs.size() > 0) {
+ unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size());
+ int high_org_id = high_rep_orgs[rand_num];
+
+ for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+ const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+
+ if (IsNeighborCellOccupied()) {
+
+ cOrganism* cur_neighbor = faced_cell->GetOrganism();
+
+ // if it has high reputation
+ if (cur_neighbor->GetID() == high_org_id) {
+ break;
+ }
+ }
+
+ cell.ConnectionList().CircNext();
+
+ }
+ }
+
+}
+
+/* Rotate an organism to face the neighbor with the highest reputation
+ where the neighbor has a different tag than the organism*/
+void cPopulationInterface::RotateToGreatestReputationWithDifferentTag(int tag)
+{
+
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
+ int high_rep=-1;
+ vector <int> high_rep_orgs;
+
+ // loop to find the max reputation
+ for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+ const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+ // cell->organism, if occupied, check reputation, etc.
+ if (IsNeighborCellOccupied()) {
+ cOrganism* cur_neighbor = faced_cell->GetOrganism();
+
+ // if it has high reputation
+ if ((cur_neighbor->GetTagLabel() != tag) && (cur_neighbor->GetReputation() >= high_rep)) {
+ if (cur_neighbor->GetReputation() > high_rep) {
+ high_rep = cur_neighbor->GetReputation();
+ high_rep_orgs.clear();
+ }
+ high_rep_orgs.push_back(cur_neighbor->GetID());
+ }
+ }
+
+ // check the next neighbor
+ cell.ConnectionList().CircNext();
+ }
+
+ // Pick an organism to donate to
+
+ if (high_rep_orgs.size() > 0) {
+ unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size());
+ int high_org_id = high_rep_orgs[rand_num];
+
+ for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+ const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+
+ if (IsNeighborCellOccupied()) {
+
+ cOrganism* cur_neighbor = faced_cell->GetOrganism();
+
+ // if it has high reputation
+ if (cur_neighbor->GetID() == high_org_id) {
+ break;
+ }
+ }
+
+ cell.ConnectionList().CircNext();
+
+ }
+
+
+
+ }
+
+}
+
+/* Rotate an organism to face the neighbor with the highest reputation
+ where the neighbor has a different tag than the organism*/
+void cPopulationInterface::RotateToGreatestReputationWithDifferentLineage(int line)
+{
+
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(GetCellID());
+ int high_rep=-1;
+ vector <int> high_rep_orgs;
+
+ // loop to find the max reputation
+ for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+ const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+ // cell->organism, if occupied, check reputation, etc.
+ if (IsNeighborCellOccupied()) {
+ cOrganism* cur_neighbor = faced_cell->GetOrganism();
+
+ // if it has high reputation
+ if ((cur_neighbor->GetLineageLabel() != line) && (cur_neighbor->GetReputation() >= high_rep)) {
+ if (cur_neighbor->GetReputation() > high_rep) {
+ high_rep = cur_neighbor->GetReputation();
+ high_rep_orgs.clear();
+ }
+ high_rep_orgs.push_back(cur_neighbor->GetID());
+ }
+ }
+
+ // check the next neighbor
+ cell.ConnectionList().CircNext();
+ }
+
+ // Pick an organism to donate to
+
+ if (high_rep_orgs.size() > 0) {
+ unsigned int rand_num = m_world->GetRandom().GetUInt(0, high_rep_orgs.size());
+ int high_org_id = high_rep_orgs[rand_num];
+
+ for(int i=0; i<cell.ConnectionList().GetSize(); ++i) {
+ const cPopulationCell* faced_cell = cell.ConnectionList().GetFirst();
+
+ if (IsNeighborCellOccupied()) {
+
+ cOrganism* cur_neighbor = faced_cell->GetOrganism();
+
+ // if it has high reputation
+ if (cur_neighbor->GetID() == high_org_id) {
+ break;
+ }
+ }
+
+ cell.ConnectionList().CircNext();
+
+ }
+
+
+
+ }
+
+}
Modified: development/source/main/cPopulationInterface.h
===================================================================
--- development/source/main/cPopulationInterface.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cPopulationInterface.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -115,6 +115,11 @@
void SendFlash();
int GetStateGridID(cAvidaContext& ctx);
+
+ // Reputation
+ void RotateToGreatestReputation();
+ void RotateToGreatestReputationWithDifferentTag(int tag);
+ void RotateToGreatestReputationWithDifferentLineage(int line);
};
Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cStats.cc 2009-05-18 20:15:08 UTC (rev 3239)
@@ -2067,3 +2067,263 @@
df.Write(num_orgs_killed, "Num Orgs Killed");
df.Endl();
} //End PrintNumOrgsKilledData()
+
+
+/* Print information pertinent to direct reciprocity experiments*/
+void cStats::PrintDirectReciprocityData(const cString& filename){
+ cDataFile& df = m_world->GetDataFile(filename);
+
+ cDoubleSum donations;
+ cDoubleSum reciprocations;
+ cDoubleSum donors;
+ cDoubleSum num_donations_received;
+
+ cOrganism* org;
+
+ int num_alt =0;
+ int num_coop = 0;
+ int num_lin_2 = 0;
+ int num_lin_1 = 0;
+ int total_org = 0;
+
+
+ df.WriteComment("Avida organism direct reciprocity information");
+ df.WriteTimeStamp();
+ df.Write(m_update, "Update [update]");
+
+
+ for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+ org = cell.GetOrganism();
+
+ if(cell.IsOccupied()) {
+ donations.Add(org->GetNumberOfDonations());
+ num_donations_received.Add(org->GetNumberOfDonationsReceived());
+ reciprocations.Add(org->GetNumberOfReciprocations());
+ donors.Add(org->GetNumberOfDonors());
+ if (org->GetNumberOfDonations() > 0) num_alt++;
+ if ((org->GetNumberOfDonationsReceived() && org->GetNumberOfDonations()) > 0) num_coop++;
+ if (org->GetLineageLabel() == 1) num_lin_1++;
+ if (org->GetLineageLabel() == 2) num_lin_2++;
+ total_org++;
+ }
+ }
+
+ df.Write(donations.Average(), "Avg. donations [donation]");
+ df.Write(num_donations_received.Average(), "Avg. donations received [received]");
+ df.Write(donors.Average(), "Avg. number of donor partners [partners]");
+ df.Write(num_alt, "Number of altruists [altruists]");
+ df.Write(num_coop, "Number of cooperators [cooperators]");
+ df.Write(num_lin_1, "Number of organisms of lineage 1 [lineage1]");
+ df.Write(num_lin_2, "Number of organisms of lineage 2 [lineage2]");
+ df.Write(total_org, "Number of organisms in population [popsize]");
+
+ df.Endl();
+
+
+}
+
+
+/* Print information about the string matching... */
+void cStats::PrintStringMatchData(const cString& filename){
+ cDataFile& df = m_world->GetDataFile(filename);
+ df.WriteComment("Avida organism string donation information");
+ df.WriteTimeStamp();
+ df.Write(m_update, "Update [update]");
+ cOrganism* org;
+
+
+ /*
+ // Interate through map of information.
+ map<cString,cDoubleSum>::iterator iter2;
+ for(iter2 = m_string_bits_matched.begin(); iter2 != m_string_bits_matched.end(); iter2++ ) {
+ df.Write(iter2->second.Average(), iter2->first);
+ }
+
+
+ // Create a map of the current tags in the population .
+ for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+ org = cell.GetOrganism();
+
+ if(cell.IsOccupied()) {
+ // Get tag and increment number of orgs.
+ m_tags[org->GetTagLabel()]++;
+ }
+ }
+
+ // print the tags
+ map<int, int>::iterator iter;
+ stringstream ss;
+ for(iter = m_tags.begin(); iter != m_tags.end(); iter++ ) {
+ ss << iter->first;
+ string name = ss.str();
+ df.Write(iter->second, name.c_str());
+ iter->second = 0;
+ }*/
+
+
+ // Print data about strings:
+ std::map <int, cDoubleSum> m_strings_stored;
+ std::map <int, cDoubleSum> m_strings_produced;
+ cDoubleSum total;
+ int min = -1;
+ int onhand = 0;
+ int instant_perfect_match = 0;
+ int instant_perfect_match_org = 0;
+ int nothing =0;
+ int specialists = 0;
+ int generalists = 0;
+ int type_prod = 0;
+
+ // Get the number of strings
+ int num = m_world->GetEnvironment().GetNumberOfMatchStrings();
+ for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+ org = cell.GetOrganism();
+ min = -1;
+ onhand = 0;
+ type_prod = 0;
+
+ if(cell.IsOccupied()) {
+ for (int j = 0; j<num; j++) {
+ onhand = org->GetNumberStringsOnHand(j);
+ if ((min == -1) || (onhand < min)){
+ min = onhand;
+ }
+ m_strings_stored[j].Add(onhand);
+ total.Add(onhand);
+ m_strings_produced[j].Add(org->GetNumberStringsProduced(j));
+
+ if (org->GetNumberStringsProduced(j)) type_prod++;
+
+ }
+
+ instant_perfect_match += min;
+ if (min > 0) instant_perfect_match_org++;
+ if (type_prod ==0) nothing++;
+ if (type_prod == 1) specialists++;
+ if (type_prod > 1) generalists++;
+ }
+
+ }
+
+ // print the string info
+ for (int k=0; k<num; k++) {
+ string name = m_world->GetEnvironment().GetMatchString(k).GetData();
+ name = "produced" + name;
+ df.Write(m_strings_produced[k].Average(), name.c_str());
+
+ name = m_world->GetEnvironment().GetMatchString(k).GetData();
+ name = "stored" + name;
+ df.Write(m_strings_stored[k].Average(), name.c_str());
+
+ }
+ df.Write(total.Average(), "totalStoredAverage");
+
+ // Print number of perfect matches
+ df.Write(m_perfect_match.Sum(), "PerfectMatchStringElapse[ps]");
+ m_perfect_match.Clear();
+ // Print number of perfect matches
+ df.Write(m_perfect_match_org.Sum(), "PerfectMatchOrgElapse[pso]");
+ m_perfect_match_org.Clear();
+ df.Write(instant_perfect_match, "PerfectMatchStringInstant[psi]");
+ // Print number of perfect matches
+ df.Write(instant_perfect_match_org, "PerfectMatchOrgInstant[psoi]");
+ df.Write(nothing, "Producednothing[nothing]");
+ df.Write(generalists, "Generalists[generalists]");
+ df.Write(specialists, "Specialists[specialists]");
+
+
+ df.Endl();
+}
+
+/* Print information about the reputation... */
+void cStats::PrintReputationData(const cString& filename){
+ cDataFile& df = m_world->GetDataFile(filename);
+
+ cDoubleSum reputations;
+ cDoubleSum donations;
+ cDoubleSum reciprocations;
+ cDoubleSum donors;
+ cDoubleSum k;
+ cDoubleSum num_donations_received;
+ cDoubleSum amount_donations_received;
+ cDoubleSum num_failed_reputation_inc;
+ cDoubleSum own_raw_mat;
+ cDoubleSum other_raw_mat;
+
+
+ // difference between how many an organism donated & how many it received
+ cDoubleSum disparity;
+
+ cOrganism* org;
+ int min_rep = 100;
+ int max_rep = 0;
+ int cur_rep;
+ int num_alt =0;
+ int num_coop = 0;
+
+
+
+ df.WriteComment("Avida organism reputation information -- average donations, min donations, max donations");
+ df.WriteTimeStamp();
+ df.Write(m_update, "Update [update]");
+
+
+ for(int i=0; i<m_world->GetPopulation().GetSize(); ++i) {
+ cPopulationCell& cell = m_world->GetPopulation().GetCell(i);
+ org = cell.GetOrganism();
+
+ if(cell.IsOccupied()) {
+ cur_rep = org->GetReputation();
+
+ if (cur_rep < min_rep) min_rep = cur_rep;
+ if (max_rep < cur_rep) max_rep = cur_rep;
+ reputations.Add(cur_rep);
+ donations.Add(org->GetNumberOfDonations());
+ num_donations_received.Add(org->GetNumberOfDonationsReceived());
+ amount_donations_received.Add(org->GetAmountOfDonationsReceived());
+ own_raw_mat.Add(org->GetSelfRawMaterials());
+ other_raw_mat.Add(org->GetOtherRawMaterials());
+
+ reciprocations.Add(org->GetNumberOfReciprocations());
+ donors.Add(org->GetNumberOfDonors());
+ num_failed_reputation_inc.Add(org->GetFailedReputationIncreases());
+// k.Add(org->GetK());
+
+ disparity.Add(org->GetNumberOfDonations() - org->GetOtherRawMaterials());
+
+ if (org->GetNumberOfDonations() > 0) num_alt++;
+ if ((org->GetNumberOfDonationsReceived() && org->GetNumberOfDonations()) > 0) num_coop++;
+
+
+ }
+ }
+ df.Write(reputations.Average(), "Avg. reputation [reputation]");
+ // df.Write(reputations.StdDeviation(), "Standard Deviation [repstddev]");
+ // df.Write(min_rep, "Minimum reputation");
+ // df.Write(max_rep, "Maximum reputation");
+ df.Write(donations.Average(), "Avg. donations [donation]");
+ // df.Write(num_donations_received.Average(), "Avg. donations received [received]");
+ // df.Write(amount_donations_received.Average(), "Avg. number donations received [amount]");
+ // df.Write(reciprocations.Average(), "Avg. reciprocations [reciprocation]");
+ // df.Write(disparity.Average(), "Disparity between donations and collections [disparity]");
+ df.Write(donors.Average(), "Avg. number of donor partners [partners]");
+ // df.Write(num_failed_reputation_inc.Average(), "Avg. number of reputation increase failures [failure]");
+ // df.Write(recip_prob_change.Average(), "Avg. change in reciprocation probability [recipprob]");
+
+ df.Write(num_alt, "Number of altruists [altruists]");
+ df.Write(num_coop, "Number of cooperators [cooperators]");
+ df.Write(own_raw_mat.Average(), "Avg. own raw mat [ownrawmat]");
+ df.Write(other_raw_mat.Average(), "Avg. other raw mat [otherrawmat]");
+ // df.Write(num_all_strings, "Number of orgs with all strings [allstrings]");
+
+ // df.Write(k.Average(), "Avg. k of organisms [k]");
+ // df.Write(m_donate_to_donor, "Number of donate to donor [donatedonor]");
+ // df.Write(m_donate_to_facing, "Number of donate to facing [donatefacing]");
+
+
+
+ df.Endl();
+}
Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cStats.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -904,9 +904,34 @@
protected:
int m_flash_count; //!< Number of flashes that have occured since last PrintSynchronizationData.
PopulationFlashes m_flash_times; //!< For tracking flashes that have occurred throughout this population.
+
+// -------- Reputation support ---------
+public:
+ // Print statistics about reputation
+ void PrintReputationData(const cString& filename);
+ void PrintDirectReciprocityData(const cString& filename);
+ void IncDonateToDonor() { m_donate_to_donor++; }
+ void IncDonateToFacing() { m_donate_to_facing++; }
+ void PrintStringMatchData(const cString& filename);
+ void AddStringBitsMatchedValue(cString name, int value) { m_string_bits_matched[name].Add(value); }
+ void AddTag(int tag, int value) { m_tags[tag] = m_tags[tag] + value; }
+ void IncPerfectMatch(int amount) { m_perfect_match.Add(amount); }
+ void IncPerfectMatchOrg() { m_perfect_match_org.Add(1); }
+
+protected:
+ int m_donate_to_donor;
+ int m_donate_to_facing;
+ std::map <cString, cDoubleSum> m_string_bits_matched;
+ cDoubleSum m_perfect_match;
+ cDoubleSum m_perfect_match_org;
+ std::map <int, int> m_tags;
+
+
};
+
+
#ifdef ENABLE_UNIT_TESTS
namespace nStats {
/**
Modified: development/source/main/cTaskLib.cc
===================================================================
--- development/source/main/cTaskLib.cc 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cTaskLib.cc 2009-05-18 20:15:08 UTC (rev 3239)
@@ -356,6 +356,9 @@
Load_MatchStr(name, info, envreqs, errors);
else if (name == "match_number")
Load_MatchNumber(name, info, envreqs, errors);
+ else if (name == "matchprodstr")
+ Load_MatchProdStr(name, info, envreqs, errors);
+
// Sequence Tasks
if (name == "sort_inputs")
@@ -419,7 +422,11 @@
else if (name == "movetoevent")
NewTask(name, "Move to a target area", &cTaskLib::Task_MoveToMovementEvent);
else if (name == "movebetweenevent")
- NewTask(name, "Move to a target area", &cTaskLib::Task_MoveBetweenMovementEvent);
+ NewTask(name, "Move to a target area", &cTaskLib::Task_MoveBetweenMovementEvent);
+
+ // reputation based tasks
+ else if(name == "perfect_strings")
+ NewTask(name, "Produce and store perfect strings", &cTaskLib::Task_CreatePerfectStrings);
// event tasks
if(name == "move_to_event")
@@ -1998,8 +2005,138 @@
return bonus;
}
+vector<cString> cTaskLib::GetMatchStrings()
+{
+ return m_strings;
+}
+cString cTaskLib::GetMatchString(int x)
+{
+ cString s;
+ if (x >= 0 && x < m_strings.size()){
+ s = m_strings[x];
+ } else {
+ s = cString("");
+ }
+
+ return s;
+
+}
+
+void cTaskLib::Load_MatchProdStr(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors)
+{
+ cArgSchema schema;
+ schema.AddEntry("string", 0, cArgSchema::SCHEMA_STRING);
+ schema.AddEntry("partial",0, 0);
+ schema.AddEntry("binary",1,1);
+ schema.AddEntry("pow",0,2.0);
+ schema.AddEntry("tag",2,-1);
+ cArgContainer* args = cArgContainer::Load(argstr, schema, errors);
+ envreqs.SetMinOutputs(args->GetString(0).GetSize());
+ m_strings.push_back(args->GetString(0));
+ if (args) NewTask(name, "MatchProdStr", &cTaskLib::Task_MatchStr, 0, args);
+}
+
+
+double cTaskLib::Task_MatchProdStr(cTaskContext& ctx) const
+{
+
+
+ // These even out the stats tracking.
+ m_world->GetStats().AddTag(ctx.GetTaskEntry()->GetArguments().GetInt(2), 0);
+ m_world->GetStats().AddTag(-1, 0);
+
+ tBuffer<int> temp_buf(ctx.GetOutputBuffer());
+
+ const cString& string_to_match = ctx.GetTaskEntry()->GetArguments().GetString(0);
+ int partial = ctx.GetTaskEntry()->GetArguments().GetInt(0);
+ int binary = ctx.GetTaskEntry()->GetArguments().GetInt(1);
+ double mypow = ctx.GetTaskEntry()->GetArguments().GetDouble(0);
+ int string_index;
+ int num_matched = 0;
+ int test_output;
+ int max_num_matched = 0;
+ int num_real=0;
+
+ if (!binary)
+ {
+ if (temp_buf.GetNumStored() > 0) {
+ test_output = temp_buf[0];
+
+ for (int j = 0; j < string_to_match.GetSize(); j++) {
+ string_index = string_to_match.GetSize() - j - 1; // start with last char in string
+ int k = 1 << j;
+ if ((string_to_match[string_index] == '0' && !(test_output & k)) ||
+ (string_to_match[string_index] == '1' && (test_output & k))) num_matched++;
+ }
+ max_num_matched = num_matched;
+ }
+ }
+ else
+ {
+ for (int j = 0; j < string_to_match.GetSize(); j++)
+ {
+ if (string_to_match[j]!='9')
+ num_real++;
+ if (string_to_match[j]=='0' && temp_buf[j]==0 ||
+ string_to_match[j]=='1' && temp_buf[j]==1)
+ num_matched++;
+ }
+ max_num_matched = num_matched;
+
+ }
+
+ // Check if the organism already produced this string.
+ // If so, it receives a perfect score for this task.
+ int tag = ctx.GetTaskEntry()->GetArguments().GetInt(2);
+
+ if (m_world->GetConfig().MATCH_ALREADY_PRODUCED.Get()) {
+ int prod = ctx.GetOrganism()->GetNumberStringsProduced(tag);
+ if (prod) max_num_matched = string_to_match.GetSize();
+ }
+
+
+ // Update the organism's tag.
+ ctx.GetOrganism()->UpdateTag(tag, max_num_matched);
+ if (ctx.GetOrganism()->GetTagLabel() == tag) {
+ ctx.GetOrganism()->SetLineageLabel(ctx.GetTaskEntry()->GetArguments().GetInt(2));
+ }
+
+
+ // Update stats
+ cString name;
+ name = "[produced";
+ name += string_to_match;
+ name += "]";
+ m_world->GetStats().AddStringBitsMatchedValue(name, max_num_matched);
+
+ // if the organism hasn't donated, then zero out its reputation.
+ if ((ctx.GetOrganism()->GetReputation() > 0) &&
+ (ctx.GetOrganism()->GetNumberOfDonations() == 0)) {
+ ctx.GetOrganism()->SetReputation(0);
+ }
+
+
+
+ double bonus = 0.0;
+ double base_bonus = 0.0;
+
+ base_bonus = static_cast<double>(max_num_matched) * 2.0 / static_cast<double>(string_to_match.GetSize()) - 1;
+
+ if (partial)
+ {
+ base_bonus=double(max_num_matched)*2/double(num_real) -1;
+ }
+
+ if (base_bonus > 0.0) {
+ bonus = pow(base_bonus,mypow);
+ }
+ return bonus;
+
+}
+
+
void cTaskLib::Load_MatchNumber(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors)
{
cArgSchema schema;
@@ -3211,3 +3348,38 @@
return quality;
}
+
+
+/* This task provides major points for perfect strings and some points for just
+ storing stuff. */
+double cTaskLib::Task_CreatePerfectStrings(cTaskContext& ctx) const {
+ double bonus = 0.0;
+ int min = -1;
+ int temp = 0;
+ for (unsigned int i = 0; i<m_strings.size(); i++) {
+ temp = ctx.GetOrganism()->GetNumberStringsOnHand(i);
+
+ // Figure out what the minimum amount of a string is.
+ if ((min == -1) || (temp < min)){
+ min = temp;
+ }
+ }
+
+ // Bonus for creating perfect strings!
+ bonus = min;
+
+ // Add in some value for just creating stuff
+ for (unsigned int i = 0; i<m_strings.size(); i++) {
+ temp = ctx.GetOrganism()->GetNumberStringsOnHand(i);
+
+ if (temp > min) {
+ bonus += (temp - min);
+ }
+ }
+
+ // Update stats
+ m_world->GetStats().IncPerfectMatch(min);
+ if (min > 0) m_world->GetStats().IncPerfectMatchOrg();
+
+ return bonus;
+}
\ No newline at end of file
Modified: development/source/main/cTaskLib.h
===================================================================
--- development/source/main/cTaskLib.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/main/cTaskLib.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -86,6 +86,15 @@
bool UseNeighborInput() const { return use_neighbor_input; }
bool UseNeighborOutput() const { return use_neighbor_output; }
+
+ // Get the strings that parameterize the MatchString tasks
+ vector<cString> GetMatchStrings();
+ cString GetMatchString(int x);
+ int GetNumberOfMatchStrings() { return m_strings.size(); }
+
+private:
+ // Store the strings used by the MatchString tasks
+ vector<cString> m_strings;
private:
@@ -242,6 +251,8 @@
// Matching Tasks
void Load_MatchStr(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors);
double Task_MatchStr(cTaskContext& ctx) const;
+ void Load_MatchProdStr(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors);
+ double Task_MatchProdStr(cTaskContext& ctx) const;
void Load_MatchNumber(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors);
double Task_MatchNumber(cTaskContext& ctx) const;
@@ -303,6 +314,9 @@
// State Grid Tasks
void Load_SGPathTraversal(const cString& name, const cString& argstr, cEnvReqs& envreqs, tList<cString>* errors);
double Task_SGPathTraversal(cTaskContext& ctx) const;
+
+ // reputation
+ double Task_CreatePerfectStrings(cTaskContext& ctx) const;
};
Modified: development/source/tools/cString.h
===================================================================
--- development/source/tools/cString.h 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/tools/cString.h 2009-05-18 20:15:08 UTC (rev 3239)
@@ -175,7 +175,12 @@
**/
int GetSize() const { return value->GetSize(); }
+ /**
+ * Get the string
+ **/
+ const char* GetData() const { return value->GetData(); }
+
// Comparisons
int Compare(const char * in) const; // strcmp like function
bool operator== (const char * in) const { return (Compare(in)==0); }
Modified: development/source/viewer-core/cCoreView_Info.cc
===================================================================
--- development/source/viewer-core/cCoreView_Info.cc 2009-05-18 17:09:16 UTC (rev 3238)
+++ development/source/viewer-core/cCoreView_Info.cc 2009-05-18 20:15:08 UTC (rev 3239)
@@ -24,7 +24,7 @@
#include "cCoreView_Info.h"
-#include "cBitArray.h"
+//#include "cBitArray.h"
#include "cClassificationManager.h"
#include "cGenotype.h"
#include "cPopulation.h"
More information about the Avida-cvs
mailing list