[Avida-SVN] r1123 - in branches/coopcomm: Avida.xcodeproj source/actions source/main source/tools

dknoester at myxo.css.msu.edu dknoester at myxo.css.msu.edu
Mon Dec 11 08:18:26 PST 2006


Author: dknoester
Date: 2006-12-11 11:18:25 -0500 (Mon, 11 Dec 2006)
New Revision: 1123

Modified:
   branches/coopcomm/Avida.xcodeproj/project.pbxproj
   branches/coopcomm/source/actions/PopulationActions.cc
   branches/coopcomm/source/actions/PrintActions.cc
   branches/coopcomm/source/main/cOrgMessage.h
   branches/coopcomm/source/main/cPopulation.cc
   branches/coopcomm/source/main/cPopulation.h
   branches/coopcomm/source/main/cStats.cc
   branches/coopcomm/source/main/cStats.h
   branches/coopcomm/source/tools/tArray.h
Log:
Added an adaptable compete demes action (rather like a combination of
ReplicateDemes and CompeteDemes) where:
- state information of each deme may be stored at intervals between competes.
- deme fitness may be calculated based on this state information.
- competes occur based on a predicate.

The "adaptable" part of this action is in the heavy use of templates to 
determine the action's behavior.



Modified: branches/coopcomm/Avida.xcodeproj/project.pbxproj
===================================================================
--- branches/coopcomm/Avida.xcodeproj/project.pbxproj	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/Avida.xcodeproj/project.pbxproj	2006-12-11 16:18:25 UTC (rev 1123)
@@ -360,23 +360,6 @@
 		E626209E0A372C2A00C07685 /* SaveLoadActions.cc in Sources */ = {isa = PBXBuildFile; fileRef = 708051A80A1F65FE00CBB8B6 /* SaveLoadActions.cc */; };
 /* End PBXBuildFile section */
 
-/* Begin PBXBuildStyle section */
-		B532BFFC0B1B4911008BEB97 /* Development */ = {
-			isa = PBXBuildStyle;
-			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-			};
-			name = Development;
-		};
-		B532BFFD0B1B4911008BEB97 /* Deployment */ = {
-			isa = PBXBuildStyle;
-			buildSettings = {
-				COPY_PHASE_STRIP = YES;
-			};
-			name = Deployment;
-		};
-/* End PBXBuildStyle section */
-
 /* Begin PBXCopyFilesBuildPhase section */
 		700E2B6D085DE50C00CF158A /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
@@ -1762,12 +1745,6 @@
 		DCC30C4D0762532C008F7A48 /* Project object */ = {
 			isa = PBXProject;
 			buildConfigurationList = 702442D70859E0B00059BD9B /* Build configuration list for PBXProject "Avida" */;
-			buildSettings = {
-			};
-			buildStyles = (
-				B532BFFC0B1B4911008BEB97 /* Development */,
-				B532BFFD0B1B4911008BEB97 /* Deployment */,
-			);
 			hasScannedForEncodings = 0;
 			mainGroup = DCC30C490762532C008F7A48;
 			productRefGroup = DCC3164E07626CF3008F7A48 /* Products */;

Modified: branches/coopcomm/source/actions/PopulationActions.cc
===================================================================
--- branches/coopcomm/source/actions/PopulationActions.cc	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/source/actions/PopulationActions.cc	2006-12-11 16:18:25 UTC (rev 1123)
@@ -7,6 +7,9 @@
  *
  */
 #include <set>
+#include <functional>
+#include <algorithm>
+#include <vector>
 
 #include "PopulationActions.h"
 
@@ -818,6 +821,285 @@
 };
 
 
+/*! \brief Determines all the different votes within a single deme.
+This is a function object that is compatible with the STL.  It is designed to be
+run iteratively over all the cells within a deme:
+
+std::for_each(cell_begin, cell_end, vote_calculator());
+*/
+struct vote_calculator : public unary_function<cPopulationCell, void> {
+  typedef std::set<cOrganism*> organism_set;
+  typedef std::map<int, organism_set > forward_votes;
+  typedef std::map<cOrganism*, organism_set*> reverse_votes;
+  typedef std::vector<std::pair<int, unsigned int> > vote_tally;
+  
+  forward_votes m_fvotes; //!< An ID-to-voters map.
+  reverse_votes m_rvotes; //!< A voter-to-group map.
+  
+  //! Called iteratively to record votes.
+  void operator()(cPopulationCell& cell) {
+    if(!cell.IsOccupied()) return;
+    cOrganism* org = cell.GetOrganism();
+    if(org->GetLeaderID() == 0) return;
+    if(!cPopulationCell::IsRandomCellID(org->GetLeaderID())) return;
+    
+    std::pair<forward_votes::iterator, bool> ins = 
+      m_fvotes.insert(std::make_pair(org->GetLeaderID(), organism_set()));
+    m_fvotes[org->GetLeaderID()].insert(org);
+    m_rvotes[org] = &m_fvotes[org->GetLeaderID()];
+  }
+  
+  template< typename Iterator >
+  void remove_votes(Iterator begin, Iterator end) {
+    for(; begin!=end; ++begin) {
+      m_fvotes.erase(*begin);
+    }
+  }
+  
+  //! Called after all votes have been recorded to tally the results.
+  template< typename TallyRider > std::pair<vote_tally, TallyRider> tally(TallyRider tr) {
+    vote_tally t;
+    for(forward_votes::const_iterator i=m_fvotes.begin(); i!=m_fvotes.end(); ++i) {
+      t.push_back(std::make_pair(i->first, i->second.size()));
+      tr(i);
+    }
+    return std::make_pair(t, tr);
+  }
+};
+
+
+/*! \brief A predicate that always competes demes.
+This is an STL-compatible function object that may be used by 
+cActionAdaptableCompeteDemes to always compete demes upon every execution of the 
+event.
+*/
+template< typename FitnessFunction >
+struct always_compete : public std::unary_function<FitnessFunction, bool> {
+  static std::string GetDescription() {
+    return "Always compete";
+  }
+  
+  always_compete(cWorld* world, const cString& args) { }
+  bool operator()(FitnessFunction& f) { return true; }
+};
+
+
+/*! \brief A predicate that competes demes at specified intervals.
+This is just a quick hack for every 100 updates...
+*/
+template< typename FitnessFunction >
+struct modulo_compete : public std::unary_function<FitnessFunction, bool> {
+  static std::string GetDescription() {
+    return "Modulo compete";
+  }
+  
+  modulo_compete(cWorld* world, const cString& args)
+  : m_world(world) {
+  }
+
+  bool operator()(FitnessFunction& f) {
+    if(m_world->GetStats().GetUpdate() % 100 == 0) {
+      return true; 
+    } else {
+      return false;
+    }
+  }
+  
+  cWorld* m_world;
+};
+
+/*! \brief Performs the standard GA-style deme competition.
+An STL-compatible function object designed to be used with 
+cActionAdaptableCompeteDemes.
+*/
+template<typename FitnessFunction>
+struct ga_competition_strategy : public std::unary_function<FitnessFunction, void> {
+  static std::string GetDescription() {
+    return "GA comp. strategy";
+  }
+  
+  ga_competition_strategy(cWorld* world, const cString& args)
+  : m_world(world) { }
+  
+  void operator()(FitnessFunction& f) {
+    m_world->GetPopulation().CompeteDemes(f.fitnesses());
+    f.reset();
+  }
+  
+  cWorld* m_world;
+};
+
+
+struct max_vote 
+: public std::unary_function<vote_calculator::forward_votes::const_iterator, void> {
+  max_vote() : m_maxID(0), m_maxVote(0) { }
+  void operator()(vote_calculator::forward_votes::const_iterator i) {
+    if(i->second.size() > m_maxVote) {
+      m_maxVote = i->second.size();
+      m_maxID = i->first;
+    }
+  }
+  int m_maxID;
+  unsigned int m_maxVote;
+};
+
+
+struct popular_vote 
+: public std::binary_function<cPopulation::t_CellIterator, cPopulation::t_CellIterator, double> {
+  static std::string GetDescription() {
+    return "popular vote";
+  }
+  
+  double operator()(cPopulation::t_CellIterator begin, cPopulation::t_CellIterator end) {
+    vote_calculator vc = std::for_each(begin, end, vote_calculator());
+    return vc.tally(max_vote()).second.m_maxVote;
+  }
+};
+
+
+template< typename DemeFitnessFunction >
+struct default_fitness : public std::unary_function<cPopulation::t_CellRangeList, void> {
+  static std::string GetDescription() {
+    return "Default fitness:" + DemeFitnessFunction::GetDescription();
+  }
+  
+  default_fitness(cWorld* world, const cString& args) { }
+  
+  void operator()(cPopulation::t_CellRangeList cell_ranges) {
+    m_fitness.clear();
+    for(cPopulation::t_CellRangeList::iterator i=cell_ranges.begin();
+        i!=cell_ranges.end();
+        ++i) {
+      DemeFitnessFunction df;
+      m_fitness.push_back(df(i->first, i->second));
+    }
+  }
+  
+  void reset() {
+  }
+  
+  const std::vector<double>& fitnesses() { return m_fitness; }
+  
+  std::vector<double> m_fitness;
+};
+
+
+struct ratcheting_popular_vote 
+: public std::binary_function<cPopulation::t_CellIterator, cPopulation::t_CellIterator, double> {
+  static std::string GetDescription() {
+    return "ratcheting popular vote";
+  }
+  
+  ratcheting_popular_vote(cWorld* world, const cString& args)
+  : m_world(world) {
+    m_previousLeaders.clear();
+  }
+  
+  /*! Calculate this deme's fitness.
+  We're guaranteed that the same ratcheting_popular_vote object will be used for
+  the same deme, so it's safe to hold some state here.  Note that state must be
+  reset after a competition event.
+  
+  In this case, we want to do the following: First, run the vote calculator.  Then,
+  tally up the votes, and remove the votes for a given set of IDs.
+  
+  The resulting fitness is max_vote^r_1 + max_vote^r_2..., where r is the number 
+  of times that this deme has beeen ratcheted.
+  */
+  double operator()(cPopulation::t_CellIterator begin, cPopulation::t_CellIterator end) {
+    vote_calculator vc = std::for_each(begin, end, vote_calculator());
+    vc.remove_votes(m_previousLeaders.begin(), m_previousLeaders.end());
+    std::pair<vote_calculator::vote_tally, max_vote> vt = vc.tally(max_vote());
+    if(vt.second.m_maxVote == 100) {
+      m_previousLeaders.push_back(vt.second.m_maxID);
+      vt.second.m_maxVote = 0;
+      // and reset the leader ID
+      cPopulationCell::GetRandomCellIDMap()[vt.second.m_maxID]->ResetRandomCellID();
+    }
+        
+    // square it so that there's always a huge benefit to getting just one more.
+    return pow(vt.second.m_maxVote + m_previousLeaders.size()*100, 2);
+  }
+  
+  std::vector<int> m_previousLeaders;
+  cWorld* m_world;
+};
+
+
+template< typename DemeFitnessFunction >
+struct stateful_fitness : public std::unary_function<cPopulation::t_CellRangeList, void> {
+  static std::string GetDescription() {
+    return "Stateful fitness:" + DemeFitnessFunction::GetDescription();
+  }
+  
+  stateful_fitness(cWorld* world, const cString& args) 
+  : m_world(world)
+  , m_args(args) {
+    reset();
+  }
+  
+  void operator()(cPopulation::t_CellRangeList cell_ranges) {
+    typedef typename std::vector<DemeFitnessFunction>::iterator dffiter;
+    cPopulation::t_CellRangeList::iterator demei = cell_ranges.begin();
+    dffiter fiti = m_demeFitness.begin();
+    m_fitness.clear();
+    for(; demei!=cell_ranges.end(); ++demei,++fiti) {
+      m_fitness.push_back((*fiti)(demei->first, demei->second));
+    }                                                                   
+  }
+
+  void reset() {
+    m_demeFitness.clear();
+    for(unsigned int i=0; i<m_world->GetPopulation().GetDemes().size(); ++i) {
+      m_demeFitness.push_back(DemeFitnessFunction(m_world,m_args));
+    }    
+  }
+  
+  const std::vector<double>& fitnesses() { return m_fitness; }
+  
+  std::vector<DemeFitnessFunction> m_demeFitness;
+  std::vector<double> m_fitness;
+  cWorld* m_world;
+  cString m_args;
+};
+
+template< typename FitnessFunction, 
+          typename CompetitionStrategy=ga_competition_strategy<FitnessFunction>,
+          typename CompetePredicate=always_compete<FitnessFunction> >
+class cActionAdaptableCompeteDemes : public cAction {
+public:
+  typedef FitnessFunction fitness_function;
+  typedef CompetitionStrategy competition_strategy;
+  typedef CompetePredicate compete_predicate;
+  
+  static const cString GetDescription() {
+    return std::string("Adaptable Deme Competition: " + 
+                       FitnessFunction::GetDescription() + " ; " + 
+                       CompetitionStrategy::GetDescription() + " ; " +
+                       CompetePredicate::GetDescription()).c_str();
+  }
+
+  cActionAdaptableCompeteDemes(cWorld* world, const cString& args)
+  : cAction(world,args)
+  , m_fit(world,args)
+  , m_comp(world,args)
+  , m_pred(world,args) {
+  }
+  
+  void Process(cAvidaContext& ctx) {
+    m_fit(m_world->GetPopulation().GetDemes());
+    if(m_pred(m_fit)) {
+      m_comp(m_fit);
+    }
+  }
+  
+private:
+  FitnessFunction m_fit;
+  CompetitionStrategy m_comp;
+  CompetePredicate m_pred;
+};
+
+
 /*
  Designed to serve as a control for the compete_demes. Each deme is 
  copied into itself and the parameters reset. 
@@ -1459,6 +1741,11 @@
   action_lib->Register<cActionAddMessagePredicate>("AddMessagePredicate");
   action_lib->Register<cActionAddBaseStationPredicate>("AddBaseStationPredicate");
   action_lib->Register<cActionMessageRain>("MessageRain");
+  action_lib->Register<
+    cActionAdaptableCompeteDemes< stateful_fitness<ratcheting_popular_vote>,
+                                  ga_competition_strategy<stateful_fitness<ratcheting_popular_vote> >,
+                                  modulo_compete<stateful_fitness<ratcheting_popular_vote> > 
+                                > >("AdaptableCompeteDemes");
   
   // @DMB - The following actions are DEPRECATED aliases - These will be removed in 2.7.
   action_lib->Register<cActionInject>("inject");

Modified: branches/coopcomm/source/actions/PrintActions.cc
===================================================================
--- branches/coopcomm/source/actions/PrintActions.cc	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/source/actions/PrintActions.cc	2006-12-11 16:18:25 UTC (rev 1123)
@@ -69,6 +69,7 @@
 STATS_OUT_FILE(PrintLeaderData, leader_log.dat);
 STATS_OUT_FILE(PrintCellData, cell_log.dat);
 STATS_OUT_FILE(PrintMessageData, message_log.dat);
+STATS_OUT_FILE(PrintDemeFitness, deme_fitness.dat);
 STATS_OUT_FILE(PrintIDData, id_log.dat);
 STATS_OUT_FILE(PrintMessageDataPerUpdate, message.dat);
 STATS_OUT_FILE(PrintMessageSnapshot, msg_snapshot.dat);
@@ -1530,6 +1531,7 @@
   action_lib->Register<cActionPrintLeaderData>("PrintLeaderData");
   action_lib->Register<cActionPrintCellData>("PrintCellData");
   action_lib->Register<cActionPrintMessageData>("PrintMessageData"); 
+  action_lib->Register<cActionPrintDemeFitness>("PrintDemeFitness");
   action_lib->Register<cActionPrintIDData>("PrintIDData");  
   action_lib->Register<cActionPrintMessageDataPerUpdate>("PrintMessageDataPerUpdate");
   action_lib->Register<cActionPrintMessageSnapshot>("PrintMessageSnapshot");

Modified: branches/coopcomm/source/main/cOrgMessage.h
===================================================================
--- branches/coopcomm/source/main/cOrgMessage.h	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/source/main/cOrgMessage.h	2006-12-11 16:18:25 UTC (rev 1123)
@@ -129,7 +129,7 @@
   cOrgMessage_PredSinkReceiverEQU(unsigned int data) : m_data(data) { }
   
   virtual bool operator()(cOrgMessage& msg) {
-    if(m_data==msg.GetReceiver()->GetCellID()) {
+    if(m_data==(unsigned int)msg.GetReceiver()->GetCellID()) {
       m_cell_ids.insert(msg.GetData());
     }
   }

Modified: branches/coopcomm/source/main/cPopulation.cc
===================================================================
--- branches/coopcomm/source/main/cPopulation.cc	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/source/main/cPopulation.cc	2006-12-11 16:18:25 UTC (rev 1123)
@@ -40,6 +40,7 @@
 #include <fstream>
 #include <vector>
 #include <algorithm>
+#include <numeric>
 #include <set>
 #include <map>
 
@@ -261,6 +262,13 @@
     }
   }
   
+  // And just for fun, let's make it a little easier to actually GET AT the list
+  // of demes and associated cells.
+  for(int i=0; i<num_demes; ++i) {
+    m_demeCellRanges.push_back(t_CellRange(cell_array.GetPtr()+i*deme_size,
+                                           cell_array.GetPtr()+(i+1)*deme_size));
+  }
+  
   return true;
 }
 
@@ -746,53 +754,48 @@
     }
       break;
     
-    case 7:
-    {
-      // Competing demes based on the number of organisms that have agreed on a leader.
-      //
-      // For each deme, build up the number of organisms that have "elected"
-      // leaders.  Total fitness is the sum of the deme_fitness; deme_fitness is
-      // the max number of organisms that have agreed on a single leader.
-      //
-      for(int cur_deme=0; cur_deme<num_demes; ++cur_deme) {
-        // for each deme...
-        cDoubleSum single_deme_fitness;
-        std::map<int, std::set<int> > votes;
-        unsigned int max=0;
-        unsigned int org_count=0;
-        
-        for (int i=0; i<deme_size; ++i) {
-          // for each cell in the deme
-          int cur_cell = cur_deme * deme_size + i;
-          // ... that has an organism
-          if (cell_array[cur_cell].IsOccupied() == false) continue;
-          // ... record the vote:
-          ++org_count;
-          cOrganism* org = GetCell(cur_cell).GetOrganism();
-          // Skip orgs that haven't set a leader.
-          if(org->GetLeaderID() == 0) continue;
-          // And skip orgs that didn't set an organism ID
-          if(!cPopulationCell::IsRandomCellID(org->GetLeaderID())) continue;
-          if(votes.find(org->GetLeaderID()) == votes.end()) {
-            votes.insert(std::make_pair(org->GetLeaderID(), std::set<int>()));
-          }
-          votes[org->GetLeaderID()].insert(org->GetRandomCellID());
-          // ... and keep track of the winning organism.
-          if(votes[org->GetLeaderID()].size() > max) {
-            max = votes[org->GetLeaderID()].size();
-          }
-        }
-
-//        if(org_count > 0) {
-          m_world->GetStats().Demes_Leadership(max, org_count);//(double)max/org_count);
-          deme_fitness[cur_deme] = (double)max;///org_count;
-          total_fitness += deme_fitness[cur_deme];
-//        } else {
-//          deme_fitness[cur_deme] = 0;
+//    case 7:
+//    {
+//      // Competing demes based on the number of organisms that have agreed on a leader.
+//      //
+//      // For each deme, build up the number of organisms that have "elected"
+//      // leaders.  Total fitness is the sum of the deme_fitness; deme_fitness is
+//      // the max number of organisms that have agreed on a single leader.
+//      //
+//      for(int cur_deme=0; cur_deme<num_demes; ++cur_deme) {
+//        // for each deme...
+//        std::map<int, std::set<int> > votes;
+//        unsigned int max=0;
+//        unsigned int org_count=0;
+//        
+//        for (int i=0; i<deme_size; ++i) {
+//          // for each cell in the deme
+//          int cur_cell = cur_deme * deme_size + i;
+//          // ... that has an organism
+//          if (cell_array[cur_cell].IsOccupied() == false) continue;
+//          // ... record the vote:
+//          ++org_count;
+//          cOrganism* org = GetCell(cur_cell).GetOrganism();
+//          // Skip orgs that haven't set a leader.
+//          if(org->GetLeaderID() == 0) continue;
+//          // And skip orgs that didn't set an organism ID
+//          if(!cPopulationCell::IsRandomCellID(org->GetLeaderID())) continue;
+//          if(votes.find(org->GetLeaderID()) == votes.end()) {
+//            votes.insert(std::make_pair(org->GetLeaderID(), std::set<int>()));
+//          }
+//          votes[org->GetLeaderID()].insert(org->GetRandomCellID());
+//          // ... and keep track of the winning organism.
+//          if(votes[org->GetLeaderID()].size() > max) {
+//            max = votes[org->GetLeaderID()].size();
+//          }
 //        }
-      }
-      break;      
-    }
+//
+//        m_world->GetStats().Demes_Leadership(max, org_count);//(double)max/org_count);
+//        deme_fitness[cur_deme] = (double)max;///org_count;
+//        total_fitness += deme_fitness[cur_deme];
+//      } // end deme-loop.
+//      break;      
+//    } // end case.
   } 
   
   // Pick which demes should be in the next generation.
@@ -868,6 +871,86 @@
 }
 
 
+void cPopulation::CompeteDemes(const std::vector<double>& deme_fitness) {
+  double total_fitness = std::accumulate(deme_fitness.begin(), 
+                                         deme_fitness.end(), 0.0);
+  m_world->GetStats().DemeFitness(deme_fitness);
+  
+  // Pick which demes should be in the next generation.
+  tArray<int> new_demes(num_demes);
+  
+  if(total_fitness > 0.0) {
+    for (int i = 0; i < num_demes; i++) {
+      double birth_choice = (double) m_world->GetRandom().GetDouble(total_fitness);
+      double test_total = 0;
+      for (int test_deme = 0; test_deme < num_demes; test_deme++) {
+        test_total += deme_fitness[test_deme];
+        if (birth_choice < test_total) {
+          new_demes[i] = test_deme;
+          break;
+        }
+      }
+    }
+  } else {
+    for(int i=0; i<num_demes; ++i) {
+      new_demes[i] = i;
+    }
+  }
+  
+  // Track how many of each deme we should have.
+  tArray<int> deme_count(num_demes);
+  deme_count.SetAll(0);
+  for (int i = 0; i < num_demes; i++) {
+    deme_count[new_demes[i]]++;
+  }
+  
+  tArray<bool> is_init(num_demes); 
+  is_init.SetAll(false);
+  
+  // Copy demes until all deme counts are 1.
+  while (true) {
+    // Find the next deme to copy...
+    int from_deme, to_deme;
+    for (from_deme = 0; from_deme < num_demes; from_deme++) {
+      if (deme_count[from_deme] > 1) break;
+    }
+    if (from_deme == num_demes) break; // If we don't find another deme to copy
+    
+    for (to_deme = 0; to_deme < num_demes; to_deme++) {
+      if (deme_count[to_deme] == 0) break;
+    }
+    
+    // We now have both a from and a to deme....
+    deme_count[from_deme]--;
+    deme_count[to_deme]++;
+    
+    // Do the actual copy!
+    for (int i = 0; i < deme_size; i++) {
+      int from_cell = from_deme * deme_size + i;
+      int to_cell = to_deme * deme_size + i;
+      if (cell_array[from_cell].IsOccupied() == true) {
+        InjectClone( to_cell, *(cell_array[from_cell].GetOrganism()) );
+      }
+    }
+    is_init[to_deme] = true;
+  }
+  
+  // Now re-inject all remaining demes into themselves to reset them.
+  for (int cur_deme = 0; cur_deme < num_demes; cur_deme++) {
+    if (is_init[cur_deme] == true) continue;
+    for (int i = 0; i < deme_size; i++) {
+      int cur_cell = cur_deme * deme_size + i;
+      if (cell_array[cur_cell].IsOccupied() == false) continue;
+      InjectClone( cur_cell, *(cell_array[cur_cell].GetOrganism()) );
+    }
+  }
+  
+  deme_birth_count.SetAll(0);
+}
+
+
+
+
 // Reset Demes goes through each deme and resets the individual organisms as
 // if they were just injected into the population.
 

Modified: branches/coopcomm/source/main/cPopulation.h
===================================================================
--- branches/coopcomm/source/main/cPopulation.h	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/source/main/cPopulation.h	2006-12-11 16:18:25 UTC (rev 1123)
@@ -41,6 +41,8 @@
 #include "tVector.h"
 #endif
 
+#include <vector>
+#include <utility>
 
 class cAvidaContext;
 class cCodeLabel;
@@ -59,6 +61,12 @@
 {
 public:
   typedef tArray<cPopulationCell> t_CellArray;
+  //! So we can iterate over ranges of cells.
+  typedef cPopulationCell* t_CellIterator;
+  //! Represents a range of cells; iteration between them must be valid.
+  typedef std::pair<cPopulationCell*, cPopulationCell*> t_CellRange;
+  //! A list of cell ranges.
+  typedef std::vector<t_CellRange> t_CellRangeList;
   
 private:
   // Components...
@@ -69,6 +77,8 @@
   cBirthChamber birth_chamber;         // Global birth chamber.
   tArray<tList<cSaleItem> > market;   // list of lists of items for sale, each list goes with 1 label
 
+  t_CellRangeList m_demeCellRanges; //!< Alternate representation of deme cells.
+  
   // Data Tracking...
   tList<cPopulationCell> reaper_queue; // Death order in some mass-action runs
   tVector<int> baseStations;
@@ -141,12 +151,17 @@
   void Kaboom(cPopulationCell& in_cell, int distance=0);
   void AddSellValue(const int data, const int label, const int sell_price, const int org_id, const int cell_id);
   int BuyValue(const int label, const int buy_price, const int cell_id);
+
   // Deme-related methods
   void CompeteDemes(int competition_type);
+  void CompeteDemes(const std::vector<double>& deme_fitness);
   void ResetDemes();
   void CopyDeme(int deme1_id, int deme2_id);
   void PrintDemeStats();
-
+  //! Returns the cell ranges that correspond to the demes in this population (assumes demes).
+  inline const t_CellRangeList GetDemes() { return m_demeCellRanges; }
+  
+  
   // Process a single organism one instruction...
   int ScheduleOrganism();          // Determine next organism to be processed.
   void ProcessStep(cAvidaContext& ctx, double step_size, int cell_id);

Modified: branches/coopcomm/source/main/cStats.cc
===================================================================
--- branches/coopcomm/source/main/cStats.cc	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/source/main/cStats.cc	2006-12-11 16:18:25 UTC (rev 1123)
@@ -98,8 +98,6 @@
   , m_data_is_sender(0)
   , m_data_is_id_and_grt_sender(0)
   , m_data_is_leader(0)
-  , m_max_deme_leadership(0)
-  , m_max_deme_count(0)
 {
   task_cur_count.Resize( m_world->GetNumTasks() );
   task_last_count.Resize( m_world->GetNumTasks() );
@@ -922,14 +920,18 @@
 }
 
 
-/*! This captures information related to using demes to elect a leader.
+/*! This captures the maximum fitness of each deme since the last stat reset.
+The max of all elements in m_maxDemeFitnesses is the global max deme fitness.
 */
-void cStats::Demes_Leadership(unsigned int max, unsigned int org_count)//double maxPct)
-{
-  if(max > m_max_deme_leadership) {
-    m_max_deme_leadership = max;
-    m_max_deme_count = org_count;
+void cStats::DemeFitness(const std::vector<double>& deme_fitness) {
+  if(m_maxDemeFitnesses.size()!=deme_fitness.size()) {
+    m_maxDemeFitnesses.resize(deme_fitness.size());
+    std::copy(deme_fitness.begin(), deme_fitness.end(), m_maxDemeFitnesses.begin());
+    return;
   }
+  for(unsigned int i=0; i<deme_fitness.size(); ++i) {
+    m_maxDemeFitnesses[i] = std::max(deme_fitness[i], m_maxDemeFitnesses[i]);
+  }
 }
 
 
@@ -1013,19 +1015,39 @@
   df.Write(m_data_is_id_and_grt_sender, "Count of messages where the data field carries an ID, and is greater than the sender's ID.");
   df.Write(m_data_is_leader, "Count of messages where the data field is the leader's ID.");
   df.Write(m_data_is_id_not_sender.Ave(), "Mean of message data fields where the data field is an ID that is not the sender's ID.");
-  df.Write(m_max_deme_leadership, "Maximum number of organisms that agreed on a leader.");
-  df.Write(m_max_deme_count, "Size of deme corresponding to max. that agreed on leader.");
   df.Endl();
   
   m_msg_data.Clear();
   m_data_is_id_not_sender.Clear();
   m_count_msgs = m_max_id = m_data_is_id = m_data_is_sender = m_data_is_id_and_grt_sender = m_data_is_leader = 0;
-  m_max_deme_leadership = 0;
-  m_max_deme_count = 0;
 }
 
 
 /*! The format of this data file is:
+<update> \
+<max deme fitness> \
+<max fitness of deme>...
+*/
+void cStats::PrintDemeFitness(const cString& filename)
+{
+  cDataFile& df = m_world->GetDataFile(filename);
+  df.WriteColumnDesc("Update.");
+  df.WriteColumnDesc("Max. deme fitness");
+  df.WriteColumnDesc("<max fitness of deme>...");
+  
+  df.WriteAnonymous(m_update);
+  df.WriteAnonymous(*std::max_element(m_maxDemeFitnesses.begin(), m_maxDemeFitnesses.end()));
+  
+  for(unsigned int i=0; i<m_maxDemeFitnesses.size(); ++i) {
+    df.WriteAnonymous(m_maxDemeFitnesses[i]);
+  }
+
+  df.Endl();
+  m_maxDemeFitnesses.clear();
+}
+
+
+/*! The format of this data file is:
 <update> <cell id>:<id>...
 
 \todo Not yet implemented.

Modified: branches/coopcomm/source/main/cStats.h
===================================================================
--- branches/coopcomm/source/main/cStats.h	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/source/main/cStats.h	2006-12-11 16:18:25 UTC (rev 1123)
@@ -258,8 +258,8 @@
   cDoubleSum m_data_is_id_not_sender; //!< Sum of message data fields where the data field is an ID that is not the sender's ID.
   std::set<int> m_cell_sent_leader; //!< Set of all cells that sent a message carrying the leader's ID.
   t_predicate_list m_predicate_list; //!< The list of predicates used to choose which messages to track.
-  unsigned int m_max_deme_leadership; //!< The maximum percentage of organisms agreeing on a leader.
-  unsigned int m_max_deme_count; //!< Count of organisms that selected a leader.
+  std::vector<double> m_maxDemeFitnesses; //!< The max fitness of each deme.
+  
   cStats(); // @not_implemented
   cStats(const cStats&); // @not_implemented
   cStats& operator=(const cStats&); // @not_implemented
@@ -606,8 +606,8 @@
   // Coop-comm.
   //! Capture information related to sending a message.
   void SentMessage(cOrgMessage& msg);
-  //! Info about leadership demes.
-  void Demes_Leadership(unsigned int max, unsigned int org_count);//double maxPct);
+  //! Captures stats related to the fitness of each deme.
+  void DemeFitness(const std::vector<double>& deme_fitness);
   //! Capture information related to organism death.
   void OrganismDeath(cOrganism* org);
   //! Log leadership-specific data.
@@ -616,6 +616,8 @@
   void PrintCellData(const cString& filename);
   //! Log message-specific data.
   void PrintMessageData(const cString& filename);
+  //! Log the max fitnesses of demes.
+  void PrintDemeFitness(const cString& filename);
   //! Log ID-specific data.
   void PrintIDData(const cString& filename);
   //! Print message data file.

Modified: branches/coopcomm/source/tools/tArray.h
===================================================================
--- branches/coopcomm/source/tools/tArray.h	2006-12-10 03:59:19 UTC (rev 1122)
+++ branches/coopcomm/source/tools/tArray.h	2006-12-11 16:18:25 UTC (rev 1123)
@@ -38,6 +38,9 @@
 
   ~tArray() { delete [] m_data; }
 
+  //! For those cases where an unchecked pointer to the data is needed...
+  inline T* GetPtr() { return m_data; }
+  
   tArray& operator=(const tArray& rhs) {
     if (m_size != rhs.GetSize())  ResizeClear(rhs.GetSize());
     for(int i = 0; i < m_size; i++) m_data[i] = rhs[i];




More information about the Avida-cvs mailing list