[Avida-SVN] r3546 - development/source/main

dk at myxo.css.msu.edu dk at myxo.css.msu.edu
Sat Dec 5 09:58:06 PST 2009


Author: dk
Date: 2009-12-05 12:58:06 -0500 (Sat, 05 Dec 2009)
New Revision: 3546

Modified:
   development/source/main/cAvidaConfig.h
   development/source/main/cGenome.cc
   development/source/main/cGenome.h
   development/source/main/cGenomeUtil.cc
   development/source/main/cGenomeUtil.h
   development/source/main/cPopulationCell.cc
   development/source/main/cPopulationInterface.cc
   development/source/main/cPopulationInterface.h
   development/source/main/cStats.cc
   development/source/main/cStats.h
Log:
hgt updates.  modularized fragment selection, added unbiased substring match.

Modified: development/source/main/cAvidaConfig.h
===================================================================
--- development/source/main/cAvidaConfig.h	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cAvidaConfig.h	2009-12-05 17:58:06 UTC (rev 3546)
@@ -664,13 +664,14 @@
 	// -------- Horizontal Gene Transfer (HGT) config options --------
 	CONFIG_ADD_GROUP(HGT_GROUP, "Horizontal gene transfer settings");
 	CONFIG_ADD_VAR(ENABLE_HGT, int, 0, "Whether HGT is enabled; 0=false (default),\n 1=true.");
+	CONFIG_ADD_VAR(HGT_FRAGMENT_SELECTION, int, 0, "Method used to select fragments for HGT mutation (0=random [default]\n1=trimmed selection).");
 	CONFIG_ADD_VAR(HGT_FRAGMENT_SIZE_MEAN, double, 10, "Mean size of fragments (drawn from a normal\ndist., default=10).");
 	CONFIG_ADD_VAR(HGT_FRAGMENT_SIZE_VARIANCE, double, 2, "Variance of fragments (drawn from a normal\ndist., default=2).");
 	CONFIG_ADD_VAR(HGT_MAX_FRAGMENTS_PER_CELL, int, 100, "Max. allowed number of fragments\nper cell (default=100).");
 	CONFIG_ADD_VAR(HGT_DIFFUSION_METHOD, int, 0, "Method to use for diffusion of genome\nfragments (0=none [default]).");
 	CONFIG_ADD_VAR(HGT_MUTATION_P, double, 0.0, "Probability that an HGT mutation will occur on divide (default=0.0).");
 	CONFIG_ADD_VAR(HGT_INSERTION_MUT_P, double, 0.5, "Probability that an HGT mutation will result in an insertion (default=0.5); replacement if false.");
-
+	
   CONFIG_ADD_GROUP(INST_RES_GROUP, "Resource-Dependent Instructions Settings");
   CONFIG_ADD_VAR(INST_RES, cString, "", "Resource upon which the execution of certain instruction depends");
   CONFIG_ADD_VAR(INST_RES_FLOOR, double, 0.0, "Assumed lower level of resource in environment.  Used for probability dist.");

Modified: development/source/main/cGenome.cc
===================================================================
--- development/source/main/cGenome.cc	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cGenome.cc	2009-12-05 17:58:06 UTC (rev 3546)
@@ -189,7 +189,78 @@
   for (int i = 0; i < genome.GetSize(); i++) m_genome[i + pos] = genome[i];
 }
 
+/*! Replace [begin, end) instructions in this genome with g, respecting genome circularity.
+ 
+ This method replaces [begin,end) instructions in this genome with those in g.  Begin and end
+ follow STL-iterator semantics, which is to say that end "points" to **one past** the last
+ instruction that will be replaced.
+ 
+ Also, circularity of the genome is respected, which means that if end < begin 
+ (the instructions that are being replaced wrap-around the end of the genome), then
+ the replacement will too.
+ 
+ Caveat: if length([begin,end)) != length(g), all size changes are made at end.
+ */
+void cGenome::Replace(const cGenome& g, int begin, int end) {
+	if(begin == end) {
+		// we're actually doing an insertion...
+		Insert(begin, g);
+	} else if(begin < end) {
+		// no wrap-around
+		Replace(begin, end-begin, g);
+	} else {
+		// replacement wraps around the end.  two different replacements to do now:
+		// [begin, size) and [0, end).
+		
+		// first, replace the [begin, size) region of this genome with as much of g
+		// as we can get.
+		int tail_size = std::min(GetSize()-begin, g.GetSize());
+		cGenome tail(&g[0], &g[0]+tail_size);
+		Replace(begin, GetSize()-begin, tail);
 
+		// now, replace the [0, end) region or remove it if the whole fragment
+		// was already copied in:
+		if(tail_size != g.GetSize()) {
+			cGenome head(&g[0]+tail_size, &g[0]+g.GetSize());
+			Replace(0, end, head);
+		} else if(end > 0) {
+			Remove(0, end);
+		}
+	}
+}
+
+/*! Rotate this genome forward n instructions.
+ 
+ "Rotation" in this sense means to move instructions from begin->end, with instructions
+ at the end wrapping around to the beginning.  Specifically, given a genome
+ [0... n... m-n... m], Rotate(n) moves instructions to create [m-n... m, 0... n].
+ 
+ Negative rotation is supported, and moves instructions from the beginning to the end.
+ */
+void cGenome::Rotate(int n) {
+	assert(n < m_active_size);
+	if(n==0) { return; }
+
+	cInstruction* begin = &operator[](0);
+	cInstruction* end = &operator[](0) + GetSize();
+	
+	if(n > 0) {
+		// forward
+		cGenome head(end-n, end);
+		cGenome tail(begin, end-n);
+		head.Append(tail);
+		operator=(head);
+	} else {
+		assert(false);
+		// backward
+		cGenome head(begin, begin-n); // n is < 0, so this is addition.
+		cGenome tail(begin-n, end);
+		tail.Append(head);
+		operator=(tail);
+	}
+}
+
+
 void cGenome::operator=(const cGenome& other_genome)
 {
   m_active_size = other_genome.m_active_size;

Modified: development/source/main/cGenome.h
===================================================================
--- development/source/main/cGenome.h	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cGenome.h	2009-12-05 17:58:06 UTC (rev 3546)
@@ -81,6 +81,10 @@
   virtual void Insert(int pos, const cGenome& genome);
   virtual void Remove(int pos, int num_sites = 1);
   virtual void Replace(int pos, int num_sites, const cGenome& genome);
+	//! Replace [begin, end) instructions in this genome with g, respecting genome circularity.
+	virtual void Replace(const cGenome& g, int begin, int end);
+	//! Rotate this genome forward n instructions.
+	virtual void Rotate(int n);
 
   inline void Append(const cInstruction& in_inst) { Insert(GetSize(), in_inst); }
   inline void Append(const cGenome& in_genome) { Insert(GetSize(), in_genome); }

Modified: development/source/main/cGenomeUtil.cc
===================================================================
--- development/source/main/cGenomeUtil.cc	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cGenomeUtil.cc	2009-12-05 17:58:06 UTC (rev 3546)
@@ -29,6 +29,7 @@
 #include "cGenome.h"
 #include "cInitFile.h"
 #include "cInstSet.h"
+#include "cRandom.h"
 #include "functions.h"
 #include <algorithm>
 #include <string.h>
@@ -245,6 +246,61 @@
 }
 
 
+/*! Distance between begin and end.
+ */
+std::size_t cGenomeUtil::substring_match::distance() {
+	std::size_t d=0;
+	if(begin <= end) {
+		d = end - begin;
+	} else {
+		d = size - begin + end;
+	}
+	return d;
+}
+
+
+/*! Resize to n (preserve the absolute distance between begin and end, based around begin).
+ */
+void cGenomeUtil::substring_match::resize(std::size_t n) {
+	// fixup begin and end if they're negative or point beyond the current size
+	if(begin < 0) { begin = size - (-begin) % size; }
+	if(end < 0) { end = size - (-end) % size; }
+	begin %= size;
+	end %= size;
+	
+	// our work is done if there's no change in size...
+	if(size == n) { return; }
+	
+	// if this is triggered, it means that the current begin index would
+	// be truncated by the new, smaller string.
+	assert(begin < static_cast<int>(n));
+	
+	// distance between begin and end:
+	std::size_t d=distance();
+	
+	// if this is triggered, it means that the new size is smaller than the
+	// region described by this match.
+	assert(d < n);
+	
+	size = n;		
+	end = (begin + d) % size;
+}
+
+
+/*! Rotate around a size of n.
+ */
+void cGenomeUtil::substring_match::rotate(int r, std::size_t n) {
+	if(r < 0) {
+		r = -((-r) % n);
+	} else {
+		r %= n;
+	}
+	begin += r;
+	end += r;
+	resize(n); // fixup the indices
+}
+
+
 /*! Find (one of) the best substring matches of substring in base.
  
  The algorithm here is based on the well-known dynamic programming approach to
@@ -265,22 +321,69 @@
 	
 	for(int i=1; i<rows; ++i) {
 		c[0].cost = i;
-		c[0].begin = 0;
 		for(int j=1; j<cols; ++j) {
 			substring_match l[3] = {p[j-1], p[j], c[j-1]};
-			substring_match* s = std::min_element(l,l+3);
+			substring_match* s = &l[0]; // default match is to the upper left.
 			
+			if(substring[i-1] == base[j-1]) {
+				// if the characters match, take the default
+				c[j].cost = s->cost;
+			} else {
+				// otherwise, find the minimum cost, add 1.
+				s = std::min_element(l,l+3);
+				c[j].cost = s->cost + 1;				
+			}
+			
+			// update the beginning and end of the match.
 			c[j].begin = s->begin;
 			c[j].end = j;
-			c[j].cost = s->cost + (substring[i-1] != base[j-1]);
 		}
 		std::swap(c,p);
 	}
 	
-	return *std::min_element(p, p+cols);
+	substring_match* min = std::min_element(p, p+cols);
+	min->size = base.GetSize();
+	return *min;
 }
 
 
+/*! Find (one of) the best unbiased matches of substring in base, respecting genome circularity.
+ 
+ Substring matches are inherently biased towards matching near to the left-hand side of the string 
+ (lower indices).  This method removes that bias by rotating the string prior to performing the
+ match.
+ 
+ Genomes in Avida are logically (not physically) circular, but substring matches in general do not 
+ respect circularity.  To respect the logical circularity of genomes in Avida, we append the base
+ string with substring-size instructions from the beginning of the base string.  This guarantees 
+ that circular matches are detected.
+ 
+ The return value here is de-circularfied and de-rotated such that [begin,end) are correct
+ for the base string (note that, due to circularity, begin could be > end).
+ */
+cGenomeUtil::substring_match cGenomeUtil::FindUnbiasedCircularMatch(cAvidaContext& ctx, const cGenome& base, const cGenome& substring) {
+	// create a copy of the genome:
+	cGenome circ(base);
+	
+	// rotate it so that we remove bias for matching at the front of the genome:
+	const int rotate = ctx.GetRandom().GetInt(circ.GetSize());
+	circ.Rotate(rotate);
+	
+	// need to take circularity of the genome into account.
+	// we can do this by appending the genome with a copy of its first substring-size instructions.
+	cGenome head(&circ[0],&circ[0]+substring.GetSize());
+	circ.Append(head);
+	
+	// find the location within the circular genome that best matches substring:
+	cGenomeUtil::substring_match location = FindSubstringMatch(circ, substring);	
+	
+	// unwind the resizing & rotation:
+	location.resize(base.GetSize());
+	location.rotate(-rotate, base.GetSize());
+	return location;
+}
+
+
 cGenome cGenomeUtil::Crop(const cGenome & in_genome, int start, int end)
 {
   assert(end > start);                // Must have a positive length clip!

Modified: development/source/main/cGenomeUtil.h
===================================================================
--- development/source/main/cGenomeUtil.h	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cGenomeUtil.h	2009-12-05 17:58:06 UTC (rev 3546)
@@ -67,18 +67,37 @@
 	 the base string is [begin, end).  (End points to the element immediately following
 	 the match).
 	 */
+	//! Substring match record.
 	struct substring_match {
 		//! Default constructor.
-		substring_match() : begin(0), end(0), cost(0) { }
-		//! Operator< overload to support std::min_element.
-		bool operator<(const substring_match& sm) { return cost < sm.cost; }
+		substring_match() : begin(0), end(0), cost(0), size(0) { }
+		//! Initializing constructor.
+		substring_match(int b, int e, int c=0, std::size_t s=0) : begin(b), end(e), cost(c), size(s) { }
+		//! Convenience method to set all values of a substring match.
+		void set(int b, int e, int c, std::size_t s) { begin = b; end = e; cost = c; size = s; }
+		//! Operator< overload.
+		bool operator<(const substring_match& that) const { return cost < that.cost; }
+		//! Operator== overload (to support testing)
+		bool operator==(const substring_match& that) const { 
+			return (begin == that.begin) && (end == that.end) && (cost == that.cost) && (size == that.size);
+		}
+		//! Distance between begin and end.
+		std::size_t distance();
+		//! Resize to n (preserve the absolute distance between begin and end, based around begin).
+		void resize(std::size_t n);
+		//! Rotate around a size of n.
+		void rotate(int r, std::size_t n);
+		
 		int begin; //!< Beginning of the substring match.
 		int end; //!< Ending of the substring match.
 		int cost; //!< Cost (edit distance) of this match.
+		std::size_t size; //!< Size of the base string.
 	};
 	
-	//! Find (one of) the best substring matches of substring in base.
-	static substring_match FindSubstringMatch(const cGenome& base, const cGenome& substring);
+	//! Find (one of) the best matches of substring in base.
+	static substring_match FindSubstringMatch(const cGenome& base, const cGenome& substring);	
+	//! Find (one of) the best unbiased matches of substring in base, respecting genome circularity.
+	static substring_match FindUnbiasedCircularMatch(cAvidaContext& ctx, const cGenome& base, const cGenome& substring);
 
   // ===== Construction methods =====
   static cGenome Crop(const cGenome& genome, int start, int end);

Modified: development/source/main/cPopulationCell.cc
===================================================================
--- development/source/main/cPopulationCell.cc	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cPopulationCell.cc	2009-12-05 17:58:06 UTC (rev 3546)
@@ -315,13 +315,21 @@
 
 	m_world->GetPopulation().AdjustHGTResource(genome.GetSize());
 
+	// copy & rotate this genome to remove bais for the beginning and end of the genome:
+	cGenome g(genome);
+	g.Rotate(m_world->GetRandom().GetInt(g.GetSize()));
+	
 	// chop this genome up into pieces, add each to the back of this cell's buffer.
-	int remaining_size=genome.GetSize();
-	const cInstruction* i=&genome[0];
+	int remaining_size=g.GetSize();
+	const cInstruction* i=&g[0];
 	do {
-		int fsize = std::min(remaining_size,
-												 (int)floor(m_world->GetRandom().GetRandNormal(m_world->GetConfig().HGT_FRAGMENT_SIZE_MEAN.Get(),
-																																			 m_world->GetConfig().HGT_FRAGMENT_SIZE_VARIANCE.Get())));
+		int fsize=0;
+		while(!fsize) {
+			fsize = std::min(remaining_size,
+											 static_cast<int>(floor(fabs(m_world->GetRandom().GetRandNormal(m_world->GetConfig().HGT_FRAGMENT_SIZE_MEAN.Get(),
+																																											m_world->GetConfig().HGT_FRAGMENT_SIZE_VARIANCE.Get())))));
+		}
+		
 		m_hgt->fragments.push_back(cGenome(i, i+fsize));
 		i+=fsize;
 		remaining_size-=fsize;

Modified: development/source/main/cPopulationInterface.cc
===================================================================
--- development/source/main/cPopulationInterface.cc	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cPopulationInterface.cc	2009-12-05 17:58:06 UTC (rev 3546)
@@ -28,13 +28,11 @@
 #include "cDeme.h"
 #include "cEnvironment.h"
 #include "cGenotype.h"
-#include "cGenomeUtil.h"
 #include "cHardwareManager.h"
 #include "cOrganism.h"
 #include "cOrgSinkMessage.h"
 #include "cOrgMessage.h"
 #include "cPopulation.h"
-#include "cPopulationCell.h"
 #include "cStats.h"
 #include "cTestCPU.h"
 
@@ -627,14 +625,12 @@
 
 /*! Perform an HGT mutation on this offspring. 
  
- HGT mutations are location-dependent, hence they are implemented here as opposed to
- the CPU or organism.
+ HGT mutations are location-dependent, hence they are piped through the populatin
+ interface as opposed to being implemented in the CPU or organism.
  
  If this method is called, an HGT mutation of some kind is imminent.  All that's left
  is to actually *do* the mutation.  We only do *one* HGT mutation each time this method
  is called.
- 
- \todo HGT should prefer more similar and older fragments.
  */
 void cPopulationInterface::DoHGTMutation(cAvidaContext& ctx, cGenome& offspring) {
 	// get this organism's cell:
@@ -642,62 +638,79 @@
 	
 	// do we have any fragments available?
 	if(cell.CountGenomeFragments() == 0) { return; }
+
+	// select the fragment and figure out where we're putting it:
+	fragment_list_type::iterator selected;
+	cGenomeUtil::substring_match location;
+	switch(m_world->GetConfig().HGT_FRAGMENT_SELECTION.Get()) {
+		case 0: { // random selection
+			HGTRandomFragmentSelection(ctx, offspring, cell.GetFragments(), selected, location);
+			break;
+		}
+		case 1: { // random selection with redundant instruction trimming
+			HGTTrimmedFragmentSelection(ctx, offspring, cell.GetFragments(), selected, location);
+			break;
+		}
+		default: { // error
+			m_world->GetDriver().RaiseFatalException(1, "HGT_FRAGMENT_SELECTION is set to an invalid value.");
+			break;
+		}
+	}
 	
-	// randomly select the genome fragment for HGT:
-	typedef cPopulationCell::fragment_list_type fragment_list_type;
-	fragment_list_type& fragments = cell.GetFragments();
-	fragment_list_type::iterator f=fragments.begin();
-	std::advance(f, ctx.GetRandom().GetInt(fragments.size()));
-	
-	// need to take circularity of the genome into account.
-	// we can do this by appending the genome with a copy of its first fragment-size
-	// instructions.  handling insertions and replacements gets complicated after this...
-	cGenome circ(offspring);
-	for(int i=0; i<f->GetSize(); ++i) {
-		circ.Append(offspring[i]);
+	// do the mutation; we currently support insertions and replacements, but this can
+	// be extended in the same way as fragment selection if need be.
+	if(ctx.GetRandom().P(m_world->GetConfig().HGT_INSERTION_MUT_P.Get())) {
+		// insert the fragment just after the final location:
+		offspring.Insert(location.end, *selected);
+	} else {
+		// replacement: replace [begin,end) instructions in the genome with the fragment,
+		// respecting circularity.
+		offspring.Replace(*selected, location.begin, location.end);
 	}
 	
+	// resource utilization, cleanup, and stats tracking:
+	m_world->GetPopulation().AdjustHGTResource(-selected->GetSize());
+	m_world->GetStats().GenomeFragmentInserted(cell.GetOrganism(), *selected, location);
+	cell.GetFragments().erase(selected);
+}
+
+
+/*! Randomly select the fragment used for HGT mutation.
+ */
+void cPopulationInterface::HGTRandomFragmentSelection(cAvidaContext& ctx, const cGenome& offspring,
+																											fragment_list_type& fragments, fragment_list_type::iterator& selected,
+																											substring_match& location) {
+	// randomly select the genome fragment for HGT:
+	selected=fragments.begin();
+	std::advance(selected, ctx.GetRandom().GetInt(fragments.size()));
+
 	// find the location within the offspring's genome that best matches the selected fragment:
-	cGenomeUtil::substring_match ssm = cGenomeUtil::FindSubstringMatch(circ, *f);
+	location = cGenomeUtil::FindUnbiasedCircularMatch(ctx, offspring, *selected);
+}
 
-	// did we match any part of the circular portion of the genome?  if so, adjust
-	// begin & end to suit.
-	if(ssm.begin > offspring.GetSize()) { ssm.begin -= offspring.GetSize(); }
-	if(ssm.end > offspring.GetSize()) { ssm.end -= offspring.GetSize(); }
 
-	// there are (currently) two supported types of HGT mutations: insertions & replacements.
-	// which one are we doing?
-	if(ctx.GetRandom().P(m_world->GetConfig().HGT_INSERTION_MUT_P.Get())) {
-		// insertion: insert the fragment just after the final location of the match:
-		offspring.Insert(ssm.end, *f);
-	} else {
-		// replacement: replace [begin,end) instructions in the genome with the fragment.
-		if(ssm.begin <= ssm.end) {
-			// match didn't wrap around the end, things are easy:
-			offspring.Replace(ssm.begin, std::max(ssm.end-ssm.begin, 1), *f);
-		} else {
-			// match wrapped around the end.  two different replacements to do now:
-			// [ssm.begin, offspring.end) and [0, ssm.end).
-						
-			// first, replace the [ssm.begin, offspring.end) region; we'll try to
-			// preserve the size of this region:
-			int tail_size = std::min(offspring.GetSize()-ssm.begin, f->GetSize());
-			cGenome tail(&(*f)[0], &(*f)[0]+tail_size);
-			offspring.Replace(ssm.begin, tail_size, tail);
-			
-			// now, replace the [0, ssm.end) region or remove it if the whole fragment
-			// was already copied in:
-			if(tail_size != f->GetSize()) {
-				cGenome head(&(*f)[0]+tail_size, &(*f)[0]+f->GetSize());
-				offspring.Replace(0, ssm.end, head);
-			} else {
-				offspring.Remove(0, ssm.end);
-			}
-		}
+/*! Randomly select the fragment used for HGT mutation, trimming redundant instructions.
+ 
+ In this fragment selection method, the fragment itself is selected randomly, but the
+ match location within the genome is calculated on a "trimmed" fragment.  Specifically,
+ the trimmed fragment has all duplicate instructions at its end removed prior to the match.
+ 
+ Mutations to the offspring are still performed using the entire fragment, so this effectively
+ increases the insertion rate.  E.g., hgt(abcde, abcccc) -> abccccde.
+ */
+void cPopulationInterface::HGTTrimmedFragmentSelection(cAvidaContext& ctx, const cGenome& offspring,
+																											 fragment_list_type& fragments, fragment_list_type::iterator& selected,
+																											 substring_match& location) {
+	// randomly select the genome fragment for HGT:
+	selected=fragments.begin();
+	std::advance(selected, ctx.GetRandom().GetInt(fragments.size()));
+	
+	// copy the selected fragment, trimming redundant instructions at the end:
+	cGenome trimmed(*selected);
+	while((trimmed.GetSize() >= 2) && (trimmed[trimmed.GetSize()-1] == trimmed[trimmed.GetSize()-2])) {
+		trimmed.Remove(trimmed.GetSize()-1);
 	}
 	
-	// resource utilization, cleanup, and stats tracking:
-	m_world->GetPopulation().AdjustHGTResource(-f->GetSize());
-	m_world->GetStats().GenomeFragmentInserted(cell.GetOrganism(), *f);
-	fragments.erase(f);
+	// find the location within the offspring's genome that best matches the selected fragment:
+	location = cGenomeUtil::FindUnbiasedCircularMatch(ctx, offspring, trimmed);
 }

Modified: development/source/main/cPopulationInterface.h
===================================================================
--- development/source/main/cPopulationInterface.h	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cPopulationInterface.h	2009-12-05 17:58:06 UTC (rev 3546)
@@ -35,12 +35,13 @@
 #ifndef cWorldDriver_h
 #include "cWorldDriver.h"
 #endif
+#include "cGenomeUtil.h"
+#include "cPopulationCell.h"
 
 class cAvidaContext;
 class cDeme;
 class cGenome;
 class cPopulation;
-class cPopulationCell;
 class cOrgMessage;
 
 class cPopulationInterface : public cOrgInterface
@@ -141,8 +142,21 @@
 	
 	// -------- HGT support --------
 public:
+	//! Container type for fragments used during HGT.
+	typedef cPopulationCell::fragment_list_type fragment_list_type;
+	//! Match record, used to indicate the region within a genome that should be mutated.
+	typedef cGenomeUtil::substring_match substring_match;
 	//! Perform an HGT mutation on this offspring.
 	void DoHGTMutation(cAvidaContext& ctx, cGenome& offspring);
+protected:
+	//! Random selection of the fragment used for HGT mutation.
+	void HGTRandomFragmentSelection(cAvidaContext& ctx, const cGenome& offspring,
+																	fragment_list_type& fragments, fragment_list_type::iterator& selected,
+																	substring_match& location);
+	//! Random selection of the fragment used for HGT mutation, with redundant instructions trimmed.
+	void HGTTrimmedFragmentSelection(cAvidaContext& ctx, const cGenome& offspring,
+																	 fragment_list_type& fragments, fragment_list_type::iterator& selected,
+																	 substring_match& location);	
 };
 
 

Modified: development/source/main/cStats.cc
===================================================================
--- development/source/main/cStats.cc	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cStats.cc	2009-12-05 17:58:06 UTC (rev 3546)
@@ -2952,7 +2952,9 @@
 	m_hgt_metabolized.Add(fragment.GetSize());
 }
 
-void cStats::GenomeFragmentInserted(cOrganism* organism, const cGenome& fragment) {
+/*! Called when a fragment is inserted into an offspring's genome via HGT.
+ */
+void cStats::GenomeFragmentInserted(cOrganism* organism, const cGenome& fragment, const cGenomeUtil::substring_match& location) {
 	m_hgt_inserted.Add(fragment.GetSize());
 }
 

Modified: development/source/main/cStats.h
===================================================================
--- development/source/main/cStats.h	2009-12-02 22:00:03 UTC (rev 3545)
+++ development/source/main/cStats.h	2009-12-05 17:58:06 UTC (rev 3546)
@@ -67,6 +67,7 @@
 #include "nGeometry.h"
 #endif
 #include "cGenome.h"
+#include "cGenomeUtil.h"
 
 #if USE_tMemTrack
 # ifndef tMemTrack_h
@@ -1031,7 +1032,7 @@
 	//! Called when an organism metabolizes a genome fragment.
 	void GenomeFragmentMetabolized(cOrganism* organism, const cGenome& fragment);
 	//! Called when an organism inserts a genome fragment.
-	void GenomeFragmentInserted(cOrganism* organism, const cGenome& fragment);
+	void GenomeFragmentInserted(cOrganism* organism, const cGenome& fragment, const cGenomeUtil::substring_match& location);
 	//! Print HGT statistics.
 	void PrintHGTData(const cString& filename);
 };




More information about the Avida-cvs mailing list