// We must also specialize the allele set so that the alleles are handled
// properly.  Be sure to handle bounds correctly whether we are discretized
// or continuous.  Handle the case where someone sets stupid bounds that 
// might cause an infinite loop for exclusive bounds.
float
GAAlleleSet<float>::allele() const {
  float value = 0.0;
  if(core->type == GAAllele::ENUMERATED)
    value = core->a[GARandomInt(0, core->sz-1)];
  else if(core->type == GAAllele::DISCRETIZED){
    float n = (core->a[1] - core->a[0]) / core->a[2];
    int m = (int)n;
    if(core->lowerb == GAAllele::EXCLUSIVE) m -= 1;
    if(core->upperb == GAAllele::EXCLUSIVE) m -= 1;
    value = core->a[0] + GARandomInt(0,(int)m) * core->a[2];
    if(core->lowerb == GAAllele::EXCLUSIVE) value += core->a[2];
  }
  else{
    if(core->a[0] == core->a[1] && 
       core->lowerb == GAAllele::EXCLUSIVE && 
       core->upperb == GAAllele::EXCLUSIVE) {
      value = core->a[0];
    }
    else {
      do {
	value = GARandomFloat(core->a[0], core->a[1]);
      } while ((core->lowerb == GAAllele::EXCLUSIVE && value == core->a[0]) ||
	       (core->upperb == GAAllele::EXCLUSIVE && value == core->a[1]));
    }
  }
  return value;
}
template <class ARRAY_TYPE> int 
GA3DArrayGenome<ARRAY_TYPE>::SwapMutator(GAGenome & c, float pmut)
{
  GA3DArrayGenome<ARRAY_TYPE> &child=(GA3DArrayGenome<ARRAY_TYPE> &)c;
  register int n, i;
  if(pmut <= 0.0) return(0);

  float nMut = pmut * (float)(child.size());
  int size = child.size()-1;
  if(nMut < 1.0){		// we have to do a flip test on each bit
    nMut = 0;
    for(i=size; i>=0; i--){
      if(GAFlipCoin(pmut)){
	child.GAArray<ARRAY_TYPE>::swap(i, GARandomInt(0, size));
	nMut++;
      }
    }
  }
  else{				// only flip the number of bits we need to flip
    for(n=0; n<nMut; n++)
      child.GAArray<ARRAY_TYPE>::swap(GARandomInt(0, size),
				      GARandomInt(0, size));
  }
  return((int)nMut);
}
Exemple #3
0
int
GA2DBinaryStringGenome::resize(int w, int h)
{
  if((unsigned int)w == nx && (unsigned int)h == ny) return sz;

  if(w == GAGenome::ANY_SIZE)
    w = GARandomInt(minX, maxX);
  else if(w < 0)
    w = nx;		// do nothing
  else if(minX == maxX)
    minX=maxX = w;
  else{
    if(w < STA_CAST(int, minX)) w=minX;
    if(w > STA_CAST(int, maxX)) w=maxX;
  }

  if(h == GAGenome::ANY_SIZE)
    h = GARandomInt(minY, maxY);
  else if(h < 0)
    h = ny;		// do nothing
  else if(minY == maxY)
    minY=maxY = h;
  else{
    if(h < STA_CAST(int, minY)) h=minY;
    if(h > STA_CAST(int, maxY)) h=maxY;
  }

// Move the bits into the right position.  If we're smaller, then shift to
// the smaller size before we do the resize (the resize method maintains bit
// integrety).  If we're larger, do the move after the resize.  If we're the 
// same size the we don't do anything.  When we're adding more bits, the new
// bits get set randomly to 0 or 1.

  if(w < STA_CAST(int,nx)){
    int y=GAMin(STA_CAST(int,ny),h);
    for(int j=0; j<y; j++)
      GABinaryString::move(j*w,j*nx,w);
  }
  GABinaryString::resize(w*h);
  if(w > STA_CAST(int,nx)){		// adjust the existing chunks of bits
    int y=GAMin(STA_CAST(int,ny),h);
    for(int j=y-1; j>=0; j--){
      GABinaryString::move(j*w,j*nx,nx);
      for(int i=nx; i<w; i++)
	bit(j*w+i, GARandomBit());
    }
  }
  if(h > STA_CAST(int,ny)){		// change in height is always new bits
    for(int i=w*ny; i<w*h; i++)
      bit(i, GARandomBit());
  }

  nx = w; ny = h;
  _evaluated = gaFalse;
  return sz;
}
Exemple #4
0
/* ----------------------------------------------------------------------------
List Genome Operators
-------------------------------------------------------------------------------
The initializer creates a list with n elements in it and puts a unique digit
in each one.  After we make the list, we scramble everything up.
---------------------------------------------------------------------------- */
void
ListInitializer(GAGenome & c)
{
  GAListGenome<int> &child=(GAListGenome<int> &)c;
  while(child.head()) child.destroy(); // destroy any pre-existing list

  int n=25;
  child.insert(0,GAListBASE::HEAD); // the head node contains a '0'
  for(int i=1; i<n; i++)
    child.insert(i);		// each subsequent node contains a number
  for(int j=0; j<n; j++)
    child.swap(GARandomInt(0,n-1), GARandomInt(0,n-1));
}
/* ----------------------------------------------------------------------------
Here is the initializer for our genomes.  It builds a list of n items of type
int.  Notice that we first destroy any list that is already in the genome 
before we do our initialization.  This is so that the genomes can be re-used.
When you re-run a GA, it does not destroy the individuals in the population - 
it reuses them.  Thus, the initializer must make sure that the genome is 
cleaned up before it tries to initialize it.
---------------------------------------------------------------------------- */
void
ListInitializer(GAGenome & c)
{
  GAListGenome<int> &child=(GAListGenome<int> &)c;

  while(child.head()) child.destroy(); // destroy any pre-existing list

  int n=75;
  child.insert(100,GAListBASE::HEAD);
  for(int i=0; i<n; i++)
    child.insert(i+100);
  for(int j=0; j<n; j++)
    child.swap(GARandomInt(0,n-1), GARandomInt(0,n-1));
}
Exemple #6
0
// Resize the population.  If we shrink, we delete the extra genomes.  If
// we grow, we clone new ones (and we DO NOT initialize them!!!).  When we
// trash the genomes, we delete the worst of the population!  We do not
// free up the space used by the array of pointers, but we do free up the
// space used by the genomes.
//   We do a clone of the genome contents so that we don't have to initialize
// the new ones (what if the population has a custom initilizer?).  We randomly
// pick which ones to clone from the existing individuals.  If the population
// contains no genomes, then we post an error message (since there are no
// individuals from which to clone the new ones).
//   If the population was evaluated, then we evaluate the new genomes.  We
// do not sort nor restat the population, and we tag the statted and sorted
// flags to reflect the fact that they are no longer valid.
//   Resizing to a bigger size is the same as a batch 'add'
int
GAPopulation::size(unsigned int popsize){
  if(popsize == n) return n;
  if(n == 0 && popsize > 0) {
    GAErr(GA_LOC, "GAPopuluation", "size", gaErrNoIndividuals);
    return n;
  }

  if(popsize > n){
    grow(popsize);
    for(unsigned int i=n; i<popsize; i++)
      rind[i] = rind[GARandomInt(0,n-1)]->clone(GAGenome::CONTENTS);
    rsorted = gaFalse;
  }
  else{
    for(unsigned int i=popsize; i<n; i++) // trash the worst ones (if sorted)
      delete rind[i];			  // may not be sorted!!!!
  }

  memcpy(sind, rind, N * sizeof(GAGenome*));
  ssorted = scaled = statted = divved = selectready = gaFalse;
  n = popsize;  

  if(evaluated == gaTrue) evaluate(gaTrue);

  return n;
}
Exemple #7
0
//   Remove the xth genome from the population.  If index is out of bounds, we
// return NULL.  Otherwise we return a pointer to the genome that was 
// removed.  The population is now no longer responsible for freeing the
// memory used by that genome.  
//   We don't touch the sorted flag for the array we modify - a remove will not
// affect the sort order.
GAGenome *
GAPopulation::remove(int i, SortBasis basis)
{
  GAGenome * removed=nullptr;
  if(i == BEST) { sort(gaFalse, basis); i = 0; }
  else if(i == WORST) { sort(gaFalse, basis); i = n-1; }
  else if(i == RANDOM) i = GARandomInt(0,n-1);
  else if(i < 0 || i >= (int)n) return removed;

  if(basis == RAW){
    removed = rind[i];
    memmove(&(rind[i]), &(rind[i+1]), (n-i-1)*sizeof(GAGenome *));
    memcpy(sind, rind, N * sizeof(GAGenome*));
    ssorted = gaFalse;
  }
  else if(basis == SCALED){
    removed = sind[i];
    memmove(&(sind[i]), &(sind[i+1]), (n-i-1)*sizeof(GAGenome *));
    memcpy(rind, sind, N * sizeof(GAGenome*));
    rsorted = gaFalse;
  }
  else return removed;

  n--;
  evaluated = gaFalse;

// *** should be smart about these and do incremental update?
  scaled = statted = divved = selectready = gaFalse;

  return removed;
}
int 
GA3DBinaryStringGenome::FlipMutator(GAGenome & c, float pmut)
{
  GA3DBinaryStringGenome &child=(GA3DBinaryStringGenome &)c;
  register int n, m, i, j, k, d;
  if(pmut <= 0.0) return(0);

  float nMut = pmut * (float)(child.size());
  if(nMut < 1.0){		// we have to do a flip test on each bit
    nMut = 0;
    for(i=child.width()-1; i>=0; i--){
      for(j=child.height()-1; j>=0; j--){
	for(k=child.depth()-1; k>=0; k--){
	  if(GAFlipCoin(pmut)){
	    child.gene(i, j, k, ((child.gene(i,j,k) == 0) ? 1 : 0));
	    nMut++;
	  }
	}
      }
    }
  }
  else{				// only flip the number of bits we need to flip
    for(n=0; n<nMut; n++){
      m = GARandomInt(0, child.size()-1);
      d = child.height() * child.depth();
      i = m / d;
      j = (m % d) / child.depth();
      k = (m % d) % child.depth();
      child.gene(i, j, k, ((child.gene(i,j,k) == 0) ? 1 : 0));
    }
  }
  return((int)nMut);
}
template <class ARRAY_TYPE> int 
GA3DArrayAlleleGenome<ARRAY_TYPE>::FlipMutator(GAGenome & c, float pmut)
{
  GA3DArrayAlleleGenome<ARRAY_TYPE> &child=
    (GA3DArrayAlleleGenome<ARRAY_TYPE> &)c;
  register int n, m, d, i, j, k;
  if(pmut <= 0.0) return(0);

  float nMut = pmut * (float)(child.size());
  if(nMut < 1.0){		// we have to do a flip test on each bit
    nMut = 0;
    for(i=child.width()-1; i>=0; i--){
      for(j=child.height()-1; j>=0; j--){
        for(k=child.depth()-1; k>=0; k--){
	  if(GAFlipCoin(pmut)){
	    child.gene(i, j, k, child.alleleset().allele());
	    nMut++;
	  }
	}
      }
    }
  }
  else{				// only flip the number of bits we need to flip
    for(n=0; n<nMut; n++){
      m = GARandomInt(0, child.size()-1);
      d = child.height() * child.depth();
      i = m / d;
      j = (m % d) / child.depth();
      k = (m % d) % child.depth();
      child.gene(i, j, k, child.alleleset().allele());
    }
  }
  return((int)nMut);
}
Exemple #10
0
int Mutator_old(GAGenome& g, float pmut)
{
    GAListGenome<int> &child=(GAListGenome<int> &)g;
    register int n, i;
    if ((GARandomFloat() >= pmut) || (pmut <= 0)) return 0;

    n = child.size();

    if (GARandomFloat()<0.5)
        {
            child.swap(GARandomInt(0,n-1),GARandomInt(0,n-1)); // swap only one time
        }
    else
        {
            int nNodes = GARandomInt(1,((int)(n/2-1)));       // displace nNodes
            child.warp(GARandomInt(0,n-1));                   // with or without
            GAList<int> TmpList;                              // inversion
            for(i=0; i<nNodes; i++)
                {
                    int *iptr = child.remove();
                    TmpList.insert(*iptr,GAListBASE::AFTER);
                    delete iptr;
                    child.next();
                }
            int invert;
            child.warp(GARandomInt(0,n-nNodes));
            invert = (GARandomFloat()<0.5) ? 0 : 1;
            if (invert) TmpList.head();
            else TmpList.tail();

            for(i=0; i<nNodes; i++)
                {
                    int *iptr = TmpList.remove();
                    child.insert(*iptr,GAListBASE::AFTER);
                    delete iptr;
                    if (invert) TmpList.prev();
                    else TmpList.next();
                }
        }
    child.head();		// set iterator to root node

    return (1);
}
Exemple #11
0
// The migrator tells the spawned populations when, where, and how many 
// individuals to move around.  This example does a single migration from one
// randomly chosen population to another randomly chosen population.  It
// chooses randomly the number of individuals to migrate.
//   One simple way to get your own migration algorithm into this is to derive
// a genetic algorithm from this class then define your own migrate method.
void
PVMDemeGA::migrate() {
  if(_ntid == 1) return;

  int fromidx, toidx;
  toidx = fromidx = GARandomInt(0, _ntid-1);
  while(fromidx == toidx) { fromidx = GARandomInt(0, _ntid-1); }

  int fromid = _tid[fromidx];
  int toid = _tid[toidx];
  int count = GARandomInt(1, deme[fromidx]->size());
  _status = pvm_initsend(PvmDataDefault);
  _status = pvm_pkint(&toid, 1, 1);
  _status = pvm_pkint(&count, 1, 1);
  _status = pvm_send(fromid, MSG_SEND_MIGRATION);

#ifdef DEBUG
  cerr << "told task " << fromid;
  cerr << " to migrate " << count << " individuals to task " << toid << "\n";
#endif
}
void CCombineGenome::Initializer( GAGenome& g)
{
	CCombineGenome& genome = (CCombineGenome&)g;
	if (m_inputData != NULL)
	{
		ComRuleData* pData = (ComRuleData*)m_inputData;
		size_t objNum = pData->m_inputData.size();
		map<YK_ID,std::list<YK_ID>>::iterator objIter = pData->m_inputData.begin();

		if (pData->m_ObjGroupLimit.empty())
		{
			int averageSize = objNum / genome.npaths();

			if (averageSize > 0)
			{
				for (int i = 0; objIter != pData->m_inputData.end(); ++i,++objIter)
				{
					int index = (i / averageSize) < genome.npaths() ?  (i / averageSize ) : (genome.npaths()-1) ;
					genome.path(index).insert(objIter->first,GAListBASE::TAIL);
				}
			}
		}else
		{
			for (; objIter != pData->m_inputData.end(); ++objIter)
			{
				YK_LLONG objId = objIter->first;
				std::set<YKString> validSet = pData->m_ObjGroupLimit[objId];

				if (!validSet.empty())
				{
					if (validSet.size() == 1)
					{
						genome.path(m_groupToIndexMap[*validSet.begin()]).insert(objIter->first,GAListBASE::TAIL);
					}else
					{
						int maxIndex = GAMin(validSet.size()-1,genome.npaths()-1);
						int index = GARandomInt(0,maxIndex);

						std::set<YKString>::iterator indexIter = validSet.begin(); 
						advance(indexIter,index);
						if (indexIter != validSet.end())
						{
							int pathNum = m_groupToIndexMap[*indexIter];
							genome.path(pathNum).insert(objId,GAListBASE::TAIL);
						}
					}
				}
			}
		}
		
	}
}
Exemple #13
0
void
DoChild(GATreeGenome<Point> & tree, int depth) {
  if(depth >= MAX_DEPTH) return;
  int n = GARandomInt(0,MAX_CHILDREN);	// maximum of 5 children

  Point p(GARandomFloat(0,25),GARandomFloat(0,25),GARandomFloat(0,25));
  tree.insert(p,GATreeBASE::BELOW);

  for(int i=0; i<n; i++)
    DoChild(tree, depth+1);

  tree.parent();		// move the iterator up one level
}
// When returning an allele from the set, we have to know what type we are.
// The allele that we return depends on the type.  If we're an enumerated set
// then just pick randomly from the list of alleles.  If we're a bounded set
// then pick randomly from the bounds, and respect the bound types.  If we're 
// a discretized set then we do much as we would for the bounded set, but we 
// respect the discretization.
//   Be sure to specialize this member function (see the real genome for an
// example of how to do this)
template <class T> T
GAAlleleSet<T>::allele() const {
  if(core->type == GAAllele::ENUMERATED)
    return core->a[GARandomInt(0, core->sz-1)];
  else if(core->type == GAAllele::DISCRETIZED){
    GAErr(GA_LOC, "GAAlleleSet", "allele(unsigned int)", gaErrOpUndef);
    return core->a[0];
  }
  else{
    GAErr(GA_LOC, "GAAlleleSet", "allele(unsigned int)", gaErrOpUndef);
    return core->a[0];
  }
}
Exemple #15
0
// change the number of populations.  try affect the evolution as little as
// possible in the process, so set things to sane values where we can.
int
GADemeGA::nPopulations(unsigned int n) {
  if(n < 1 || n == npop) return npop;
  if(n < npop) {
    for(unsigned int i=n; i<npop; i++)
      delete deme[i];
    GAPopulation** ptmp = deme;
    deme = new GAPopulation* [n];
    memcpy(deme, ptmp, n * sizeof(GAPopulation*));
    delete [] ptmp;

    GAStatistics* stmp = pstats;
    pstats = new GAStatistics[n];
    for(unsigned int j=0; j<n; j++)
      pstats[j] = stmp[j];
    delete [] stmp;

    int* rtmp = nrepl;
    nrepl = new int[n];
    memcpy(nrepl, rtmp, n * sizeof(int));
    delete [] rtmp;

    npop = n;
  }
  else {
    GAPopulation** ptmp = deme;
    deme = new GAPopulation* [n];
    memcpy(deme, ptmp, npop * sizeof(GAPopulation*));
    delete [] ptmp;
    for(unsigned int i=npop; i<n; i++)
      deme[i] = new GAPopulation(*deme[GARandomInt(0,npop-1)]);

    GAStatistics* stmp = pstats;
    pstats = new GAStatistics[n];
    for(unsigned int j=0; j<npop; j++)
      pstats[j] = stmp[j];
    delete [] stmp;

    int* rtmp = nrepl;
    nrepl = new int[n];
    memcpy(nrepl, rtmp, npop * sizeof(int));
    for(unsigned int k=npop; k<n; k++)
      nrepl[k] = nrepl[0];    

    npop = n;
  }
  params.set(gaNnPopulations, (unsigned int)n);
  pop->size(npop);
  return npop;
}
Exemple #16
0
void
TreeInitializer(GAGenome & c) {
  GATreeGenome<Point> &tree=(GATreeGenome<Point> &)c;

// destroy any pre-existing tree
  tree.root();
  tree.destroy();

// create a root node with coordinates 0,0,0, then do the rest.
  Point p(0,0,0);
  tree.insert(p,GATreeBASE::ROOT);
  int n = GARandomInt(0,MAX_CHILDREN);	// maximum of 5 children
  for(int i=0; i<n; i++)
    DoChild(tree, 0);
}
//   Resize the genome.
//   A negative value for the length means that we should randomly set the
// length of the genome (if the resize behaviour is resizeable).  If
// someone tries to randomly set the length and the resize behaviour is fixed
// length, then we don't do anything.
//   We pay attention to the values of minX and maxX - they determine what kind
// of resizing we are allowed to do.  If a resize is requested with a length
// less than the min length specified by the behaviour, we set the minimum
// to the length.  If the length is longer than the max length specified by
// the behaviour, we set the max value to the length.
//   We return the total size (in bits) of the genome after resize.
//   We don't do anything to the new contents!
template <class T> int
GA1DArrayGenome<T>::resize(int len)
{
    if(len == STA_CAST(int,nx)) return nx;

    if(len == GAGenome::ANY_SIZE)
        len = GARandomInt(minX, maxX);
    else if(len < 0)
        return nx;			// do nothing
    else if(minX == maxX)
        minX=maxX=len;
    else {
        if(len < STA_CAST(int,minX)) len=minX;
        if(len > STA_CAST(int,maxX)) len=maxX;
    }

    nx = GAArray<T>::size(len);
    _evaluated = gaFalse;
    return this->sz;
}
Exemple #18
0
// Randomly pick bits in the bit string then flip their values.  We try to be
// smart about the number of times we have to call any random functions.  If
// the requested likliehood is small enough (relative to the number of bits in
// the genome) then we must do a weighted coin toss on each bit in the genome.
// Otherwise, we just do the expected number of flips (note that this will not
// guarantee the requested mutation rate, but it will come close when the
// length of the bit string is long enough).
int 
BitStringGenome::UniformMutator(GAGenome & c, float pmut) {
  BitStringGenome &genome=(BitStringGenome &)c;
  register int n, i;
  if(pmut <= 0.0) return(0);

  float nMut = pmut * (float)(genome.length());
  if(nMut < 1.0){		// we have to do a flip test on each bit
    nMut = 0;
    for(i=genome.length()-1; i>=0; i--){
      if(GAFlipCoin(pmut)){
	genome.gene(i, genome.gene(i) ? 0 : 1);
	nMut++;
      }
    }
  }
  else{				// only flip the number of bits we need to flip
    for(n=1; n<nMut; n++){
      i = GARandomInt(0, genome.length()-1); // the index of the bit to flip
      genome.gene(i, genome.gene(i) ? 0 : 1);
    }
  }
  return (int)nMut;
}
//   Resize the genome.  If someone specifies ANY_RESIZE then we pick a random
// size within the behaviour limits that have been set.  If limits have been
// set and someone passes us something outside the limits, we resize to the
// closest bound.  If the genome is fixed size (ie min limit equals max limit)
// then we resize to the specified value and move the min/max to match it.
int
GA1DBinaryStringGenome::resize(int l)
{
  if(l == STA_CAST(int, nx)) return nx;

  if(l == GAGenome::ANY_SIZE)
    l = GARandomInt(minX, maxX);
  else if(l < 0)
    return nx;			// do nothing
  else if(minX == maxX)
    minX=maxX=l;
  else{
    if(l < STA_CAST(int, minX)) l=minX;
    if(l > STA_CAST(int, maxX)) l=maxX;
  }

  GABinaryString::resize(l);
  if(l > STA_CAST(int, nx))
    for(int i=nx; i<l; i++)
      bit(i, GARandomBit());
  nx = l;
  _evaluated = gaFalse;
  return sz;
}
// Pick a single point in the 3D block and grab alternating quadrants for each
// child.  If the children are resizable, this crossover does clipping.
template <class T> int
GA3DArrayGenome<T>::
OnePointCrossover(const GAGenome& p1, const GAGenome& p2,
		  GAGenome* c1, GAGenome* c2){
  GA3DArrayGenome<T> &mom=(GA3DArrayGenome<T> &)p1;
  GA3DArrayGenome<T> &dad=(GA3DArrayGenome<T> &)p2;

  int nc=0;
  unsigned int momsitex, momlenx, momsitey, momleny, momsitez, momlenz;
  unsigned int dadsitex, dadlenx, dadsitey, dadleny, dadsitez, dadlenz;
  unsigned int sitex, lenx, sitey, leny, sitez, lenz;

  if(c1 && c2){
    GA3DArrayGenome<T> &sis=(GA3DArrayGenome<T> &)*c1;
    GA3DArrayGenome<T> &bro=(GA3DArrayGenome<T> &)*c2;

    if(sis.resizeBehaviour(GAGenome::WIDTH) == GAGenome::FIXED_SIZE &&
       bro.resizeBehaviour(GAGenome::WIDTH) == GAGenome::FIXED_SIZE){
      if(mom.width() != dad.width() || 
	 sis.width() != bro.width() || 
	 sis.width() != mom.width()){
	GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameLengthReqd);
	return nc;
      }
      sitex = momsitex = dadsitex = GARandomInt(0, mom.width());
      lenx = momlenx = dadlenx = mom.width() - momsitex;
    }
    else if(sis.resizeBehaviour(GAGenome::WIDTH) == GAGenome::FIXED_SIZE ||
	    bro.resizeBehaviour(GAGenome::WIDTH) == GAGenome::FIXED_SIZE){
      GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameBehavReqd);
      return nc;
    }
    else{
      momsitex = GARandomInt(0, mom.width());
      dadsitex = GARandomInt(0, dad.width());
      momlenx = mom.width() - momsitex;
      dadlenx = dad.width() - dadsitex;
      sitex = GAMin(momsitex, dadsitex);
      lenx = GAMin(momlenx, dadlenx);
    }
    
    if(sis.resizeBehaviour(GAGenome::HEIGHT) == GAGenome::FIXED_SIZE &&
       bro.resizeBehaviour(GAGenome::HEIGHT) == GAGenome::FIXED_SIZE){
      if(mom.height() != dad.height() || 
	 sis.height() != bro.height() || 
	 sis.height() != mom.height()){
	GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameLengthReqd);
	return nc;
      }
      sitey = momsitey = dadsitey = GARandomInt(0, mom.height());
      leny = momleny = dadleny = mom.height() - momsitey;
    }
    else if(sis.resizeBehaviour(GAGenome::HEIGHT) == GAGenome::FIXED_SIZE ||
	    bro.resizeBehaviour(GAGenome::HEIGHT) == GAGenome::FIXED_SIZE){
      GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameBehavReqd);
      return nc;
    }
    else{
      momsitey = GARandomInt(0, mom.height());
      dadsitey = GARandomInt(0, dad.height());
      momleny = mom.height() - momsitey;
      dadleny = dad.height() - dadsitey;
      sitey = GAMin(momsitey, dadsitey);
      leny = GAMin(momleny, dadleny);
    }

    if(sis.resizeBehaviour(GAGenome::DEPTH) == GAGenome::FIXED_SIZE &&
       bro.resizeBehaviour(GAGenome::DEPTH) == GAGenome::FIXED_SIZE){
      if(mom.depth() != dad.depth() || 
	 sis.depth() != bro.depth() || 
	 sis.depth() != mom.depth()){
	GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameLengthReqd);
	return nc;
      }
      sitez = momsitez = dadsitez = GARandomInt(0, mom.depth());
      lenz = momlenz = dadlenz = mom.depth() - momsitez;
    }
    else if(sis.resizeBehaviour(GAGenome::DEPTH) == GAGenome::FIXED_SIZE ||
	    bro.resizeBehaviour(GAGenome::DEPTH) == GAGenome::FIXED_SIZE){
      GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameBehavReqd);
      return nc;
    }
    else{
      momsitez = GARandomInt(0, mom.depth());
      dadsitez = GARandomInt(0, dad.depth());
      momlenz = mom.depth() - momsitez;
      dadlenz = dad.depth() - dadsitez;
      sitez = GAMin(momsitez, dadsitez);
      lenz = GAMin(momlenz, dadlenz);
    }

    sis.resize(sitex+lenx, sitey+leny, sitez+lenz);
    bro.resize(sitex+lenx, sitey+leny, sitez+lenz);

    sis.copy(mom, 
	     0, 0, 0, 
	     momsitex-sitex, momsitey-sitey, momsitez-sitez,
	     sitex, sitey, sitez);
    sis.copy(dad,
	     sitex, 0, 0,
	     dadsitex, dadsitey-sitey, dadsitez-sitez,
	     lenx, sitey, sitez);
    sis.copy(dad,
	     0, sitey, 0,
	     dadsitex-sitex, dadsitey, dadsitez-sitez,
	     sitex, leny, sitez);
    sis.copy(mom,
	     sitex, sitey, 0,
	     momsitex, momsitey, momsitez-sitez,
	     lenx, leny, sitez);
    sis.copy(dad, 
	     0, 0, sitez, 
	     dadsitex-sitex, dadsitey-sitey, dadsitez,
	     sitex, sitey, lenz);
    sis.copy(mom,
	     sitex, 0, sitez,
	     momsitex, momsitey-sitey, momsitez,
	     lenx, sitey, lenz);
    sis.copy(mom,
	     0, sitey, sitez,
	     momsitex-sitex, momsitey, momsitez,
	     sitex, leny, lenz);
    sis.copy(dad,
	     sitex, sitey, sitez,
	     dadsitex, dadsitey, dadsitez,
	     lenx, leny, lenz);
    
    bro.copy(dad, 
	     0, 0, 0, 
	     dadsitex-sitex, dadsitey-sitey, dadsitez-sitez,
	     sitex, sitey, sitez);
    bro.copy(mom,
	     sitex, 0, 0,
	     momsitex, momsitey-sitey, momsitez-sitez,
	     lenx, sitey, sitez);
    bro.copy(mom,
	     0, sitey, 0,
	     momsitex-sitex, momsitey, momsitez-sitez,
	     sitex, leny, sitez);
    bro.copy(dad,
	     sitex, sitey, 0,
	     dadsitex, dadsitey, dadsitez-sitez,
	     lenx, leny, sitez);
    bro.copy(mom, 
	     0, 0, sitez, 
	     momsitex-sitex, momsitey-sitey, momsitez,
	     sitex, sitey, lenz);
    bro.copy(dad,
	     sitex, 0, sitez,
	     dadsitex, dadsitey-sitey, dadsitez,
	     lenx, sitey, lenz);
    bro.copy(dad,
	     0, sitey, sitez,
	     dadsitex-sitex, dadsitey, dadsitez,
	     sitex, leny, lenz);
    bro.copy(mom,
	     sitex, sitey, sitez,
	     momsitex, momsitey, momsitez,
	     lenx, leny, lenz);

    nc = 2;
  }
  else if(c1){
    GA3DArrayGenome<T> &sis=(GA3DArrayGenome<T> &)*c1;

    if(sis.resizeBehaviour(GAGenome::WIDTH) == GAGenome::FIXED_SIZE){
      if(mom.width() != dad.width() || sis.width() != mom.width()){
	GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameLengthReqd);
	return nc;
      }
      sitex = momsitex = dadsitex = GARandomInt(0, mom.width());
      lenx = momlenx = dadlenx = mom.width() - momsitex;
    }
    else{
      momsitex = GARandomInt(0, mom.width());
      dadsitex = GARandomInt(0, dad.width());
      momlenx = mom.width() - momsitex;
      dadlenx = dad.width() - dadsitex;
      sitex = GAMin(momsitex, dadsitex);
      lenx = GAMin(momlenx, dadlenx);
    }
    
    if(sis.resizeBehaviour(GAGenome::HEIGHT) == GAGenome::FIXED_SIZE){
      if(mom.height() != dad.height() || sis.height() != mom.height()){
	GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameLengthReqd);
	return nc;
      }
      sitey = momsitey = dadsitey = GARandomInt(0, mom.height());
      leny = momleny = dadleny = mom.height() - momsitey;
    }
    else{
      momsitey = GARandomInt(0, mom.height());
      dadsitey = GARandomInt(0, dad.height());
      momleny = mom.height() - momsitey;
      dadleny = dad.height() - dadsitey;
      sitey = GAMin(momsitey, dadsitey);
      leny = GAMin(momleny, dadleny);
    }

    if(sis.resizeBehaviour(GAGenome::DEPTH) == GAGenome::FIXED_SIZE){
      if(mom.depth() != dad.depth() || sis.depth() != mom.depth()){
	GAErr(GA_LOC, mom.className(), "one-point cross", gaErrSameLengthReqd);
	return nc;
      }
      sitez = momsitez = dadsitez = GARandomInt(0, mom.depth());
      lenz = momlenz = dadlenz = mom.depth() - momsitez;
    }
    else{
      momsitez = GARandomInt(0, mom.depth());
      dadsitez = GARandomInt(0, dad.depth());
      momlenz = mom.depth() - momsitez;
      dadlenz = dad.depth() - dadsitez;
      sitez = GAMin(momsitez, dadsitez);
      lenz = GAMin(momlenz, dadlenz);
    }
    
    sis.resize(sitex+lenx, sitey+leny, sitez+lenz);
    
    if(GARandomBit()){
      sis.copy(mom, 
	       0, 0, 0, 
	       momsitex-sitex, momsitey-sitey, momsitez-sitez,
	       sitex, sitey, sitez);
      sis.copy(dad,
	       sitex, 0, 0,
	       dadsitex, dadsitey-sitey, dadsitez-sitez,
	       lenx, sitey, sitez);
      sis.copy(dad,
	       0, sitey, 0,
	       dadsitex-sitex, dadsitey, dadsitez-sitez,
	       sitex, leny, sitez);
      sis.copy(mom,
	       sitex, sitey, 0,
	       momsitex, momsitey, momsitez-sitez,
	       lenx, leny, sitez);
      sis.copy(dad, 
	       0, 0, sitez, 
	       dadsitex-sitex, dadsitey-sitey, dadsitez,
	       sitex, sitey, lenz);
      sis.copy(mom,
	       sitex, 0, sitez,
	       momsitex, momsitey-sitey, momsitez,
	       lenx, sitey, lenz);
      sis.copy(mom,
	       0, sitey, sitez,
	       momsitex-sitex, momsitey, momsitez,
	       sitex, leny, lenz);
      sis.copy(dad,
	       sitex, sitey, sitez,
	       dadsitex, dadsitey, dadsitez,
	       lenx, leny, lenz);
    }
    else{
      sis.copy(dad, 
	       0, 0, 0, 
	       dadsitex-sitex, dadsitey-sitey, dadsitez-sitez,
	       sitex, sitey, sitez);
      sis.copy(mom,
	       sitex, 0, 0,
	       momsitex, momsitey-sitey, momsitez-sitez,
	       lenx, sitey, sitez);
      sis.copy(mom,
	       0, sitey, 0,
	       momsitex-sitex, momsitey, momsitez-sitez,
	       sitex, leny, sitez);
      sis.copy(dad,
	       sitex, sitey, 0,
	       dadsitex, dadsitey, dadsitez-sitez,
	       lenx, leny, sitez);
      sis.copy(mom, 
	       0, 0, sitez, 
	       momsitex-sitex, momsitey-sitey, momsitez,
	       sitex, sitey, lenz);
      sis.copy(dad,
	       sitex, 0, sitez,
	       dadsitex, dadsitey-sitey, dadsitez,
	       lenx, sitey, lenz);
      sis.copy(dad,
	       0, sitey, sitez,
	       dadsitex-sitex, dadsitey, dadsitez,
	       sitex, leny, lenz);
      sis.copy(mom,
	       sitex, sitey, sitez,
	       momsitex, momsitey, momsitez,
	       lenx, leny, lenz);
    }

    nc = 1;
  }

  return nc;
}
template <class T> int
GA3DArrayGenome<T>::resize(int w, int h, int d)
{
  if(w == (int)nx && h == (int)ny && d == (int)nz) return sz;

  if(w == GAGenome::ANY_SIZE)
    w = GARandomInt(minX, maxX);
  else if(w < 0)
    w = nx;		// do nothing
  else if(minX == maxX)
    minX=maxX = w;
  else{
    if(w < (int)minX) w=minX;
    if(w > (int)maxX) w=maxX;
  }

  if(h == GAGenome::ANY_SIZE)
    h = GARandomInt(minY, maxY);
  else if(h < 0)
    h = ny;		// do nothing
  else if(minY == maxY)
    minY=maxY = h;
  else{
    if(h < (int)minY) h=minY;
    if(h > (int)maxY) h=maxY;
  }

  if(d == GAGenome::ANY_SIZE)
    d = GARandomInt(minZ, maxZ);
  else if(d < 0)
    d = nz;		// do nothing
  else if(minZ == maxZ)
    minZ=maxZ = d;
  else{
    if(d < (int)minZ) d=minZ;
    if(d > (int)maxZ) d=maxZ;
  }

  if(w < (int)nx && h < (int)ny){
    int z=GAMin((int)nz,d);
    for(int k=0; k<z; k++)
      for(int j=0; j<h; j++)
	GAArray<T>::move(k*h*w+j*w,k*ny*nx+j*nx,w);
  }
  else if(w < (int)nx){
    int z=GAMin((int)nz,d);
    for(int k=0; k<z; k++)
      for(int j=0; j<(int)ny; j++)
	GAArray<T>::move(k*ny*w+j*w,k*ny*nx+j*nx,w);
  }
  else if(h < (int)ny){
    int z=GAMin((int)nz,d);
    for(int k=0; k<z; k++)
      for(int j=0; j<h; j++)
	GAArray<T>::move(k*h*nx+j*nx,k*ny*nx+j*nx,nx);
  }

  GAArray<T>::size(w*h*d);

  if(w > (int)nx && h > (int)ny){ 
    int z=GAMin((int)nz,d);
    for(int k=z-1; k>=0; k--)
      for(int j=ny-1; j>=0; j--)
	GAArray<T>::move(k*h*w+j*w,k*ny*nx+j*nx,nx);
  }
  else if(w > (int)nx){
    int z=GAMin((int)nz,d);
    for(int k=z-1; k>=0; k--)
      for(int j=h-1; j>=0; j--)
	GAArray<T>::move(k*h*w+j*w,k*h*nx+j*nx,nx);
  }
  else if(h > (int)ny){
    int z=GAMin((int)nz,d);
    for(int k=z-1; k>=0; k--)
      for(int j=ny-1; j>=0; j--)
	GAArray<T>::move(k*h*w+j*w,k*ny*w+j*w,w);
  }

  nx = w; ny = h; nz = d;
  _evaluated = gaFalse;
  return sz;
}
Exemple #22
0
// Replace the specified genome with the one that is passed to us then 
// return the one that got replaced.  Use the replacement flags to determine
// which genome will be replaced.  If we get a genome as the second
// argument, then replace that one.  If we get a NULL genome, then we
// return a NULL and don't do anything.
//   If the population is sorted, then we maintain the sort by doing a smart
// replacement.
//   If the population is not sorted, then we just do the replacement without
// worrying about the sort.  Replace best and worst both require that we know
// which chromsomes are which, so we do a sort before we do the replacement,
// then we do a smart replacement.
//   In both cases we flag the stats as out-of-date, but we do not update the
// stats.  Let that happen when it needs to happen.
//   If which is < 0 then it is a flag that tells us to do a certain kind of
// replacement.  Anything non-negative is assumed to be an index to a 
// genome in the population.
//   This does not affect the state of the evaluated member - it assumes that
// the individual genome has a valid number for its score.
GAGenome *
GAPopulation::replace(GAGenome * repl, int which, SortBasis basis)
{
  int i=-1;
  GAGenome * orig=nullptr;
  if(repl == nullptr) return orig;

  switch(which){
  case BEST:
    sort(gaFalse, basis);
    i = 0;
    break;
      
  case WORST:
    sort(gaFalse, basis);
    i = n-1;
    break;

  case RANDOM:
    i = GARandomInt(0, n-1);
    break;

  default:
    if(0 <= which && which < (int)n)
      i = which;
    break;
  }

  if(i >= 0){
// We could insert this properly if the population is sorted, but that would
// require us to evaluate the genome, and we don't want to do that 'cause that
// will screw up any parallel implementations.  So we just stick it in the
// population and let the sort take care of it at a later time as needed.
    if(basis == RAW){
      orig = rind[i];		// keep the original to return at the end
      rind[i] = repl;
      memcpy(sind, rind, N * sizeof(GAGenome*));
    }
    else{
      orig = sind[i];		// keep the original to return at the end
      sind[i] = repl;
      memcpy(rind, sind, N * sizeof(GAGenome*));
    }
    rsorted = ssorted = gaFalse;	// must sort again
// flag for recalculate stats
    statted = gaFalse;
// Must flag for a new evaluation.
    evaluated = gaFalse;
// No way to do incremental update of scaling info since we don't know what the
// scaling object will do.
    scaled = gaFalse;
// *** should do an incremental update of the diversity here so we don't 
// recalculate all of the diversities when only one is updated
    divved = gaFalse;
// selector needs update
    selectready = gaFalse;

// make sure the genome has the correct genetic algorithm pointer
    if(ga) repl->geneticAlgorithm(*ga);
  }

  return orig;
}
int CCombineGenome::Mutator( GAGenome& g, float pmut)
{
	CCombineGenome& genome = (CCombineGenome&)g;
	genome.SetEvaluated(gaFalse);
	int nMut = 1;

	if(genome.npaths() <= 1)
		return nMut;

	int first = 0;
	int second = 0;
	
	first = GARandomInt(0,genome.npaths()-1);
	second = GARandomInt(0,genome.npaths()-1);
	
	int nfirstSize = genome.path(first).size();
	if (nfirstSize > 0)
	{
		if (m_inputData != NULL && !((ComRuleData*)m_inputData)->m_ObjGroupLimit.empty())
		{
			YKString firstGroupName = m_indexToGroupMap[first];

			vector<int> validMoveIndexVec;
			int listIndex = 0;

			for (int i = 0; i < nfirstSize; ++i)
			{
				YK_LLONG objID = *genome.path(first).warp(i);
				set<YKString> validSet = ((ComRuleData*)m_inputData)->m_ObjGroupLimit[objID];
				validSet.erase(firstGroupName);
				if (validSet.size() > 0)
				{
					validMoveIndexVec.push_back(i);
				}
			}
			if (validMoveIndexVec.size() > 0)
			{
				int vecIndex = GARandomInt(0,validMoveIndexVec.size()-1);
				listIndex = validMoveIndexVec[vecIndex];

				YK_LLONG curObjID = *genome.path(first).warp(listIndex);

				set<YKString> validSet = ((ComRuleData*)m_inputData)->m_ObjGroupLimit[curObjID];
				validSet.erase(firstGroupName);
				if (validSet.size() > 0)
				{
					std::set<YKString>::iterator indexIter = validSet.begin();
					int randNum = GARandomInt(0,validSet.size()-1);
					advance(indexIter,randNum);
					if (indexIter != validSet.end())
					{
						second = m_groupToIndexMap[*indexIter];
					}
				}

				genome.path(second).insert(curObjID,GAListBASE::TAIL);
				if (listIndex != genome.path(first).size()-1)
				{
					genome.path(first).swap(listIndex,genome.path(first).size()-1);
				}
				genome.path(first).tail();

				genome.path(first).remove();
			}
		}else
		{
			int index = GARandomInt(0,nfirstSize-1);

			while (first == second)
			{
				second = GARandomInt(0,genome.npaths()-1);
			}

			genome.path(second).insert(*genome.path(first).warp(index),GAListBASE::TAIL);
			if (index != genome.path(first).size()-1)
			{
				genome.path(first).swap(index,genome.path(first).size()-1);
			}
			genome.path(first).tail();

			genome.path(first).remove();
		}
		  
	}

	return nMut;
}
int
GA3DBinaryStringGenome::resize(int w, int h, int d)
{
  if(w == (int)nx && h == (int)ny && d == (int)nz) return sz;

  if(w == GAGenome::ANY_SIZE)
    w = GARandomInt(minX, maxX);
  else if(w < 0)
    w = nx;		// do nothing
  else if(minX == maxX)
    minX=maxX = w;
  else{
    if(w < (int)minX) w=minX;
    if(w > (int)maxX) w=maxX;
  }

  if(h == GAGenome::ANY_SIZE)
    h = GARandomInt(minY, maxY);
  else if(h < 0)
    h = ny;		// do nothing
  else if(minY == maxY)
    minY=maxY = h;
  else{
    if(h < (int)minY) h=minY;
    if(h > (int)maxY) h=maxY;
  }

  if(d == GAGenome::ANY_SIZE)
    d = GARandomInt(minZ, maxZ);
  else if(d < 0)
    d = nz;		// do nothing
  else if(minZ == maxZ)
    minZ=maxZ = d;
  else{
    if(d < (int)minZ) d=minZ;
    if(d > (int)maxZ) d=maxZ;
  }

  if(w < (int)nx && h < (int)ny){
    int z=GAMin((int)nz,d);
    for(int k=0; k<z; k++)
      for(int j=0; j<h; j++)
	GABinaryString::move(k*h*w+j*w,k*ny*nx+j*nx,w);
  }
  else if(w < (int)nx){
    int z=GAMin((int)nz,d);
    for(int k=0; k<z; k++)
      for(int j=0; j<(int)ny; j++)
	GABinaryString::move(k*ny*w+j*w,k*ny*nx+j*nx,w);
  }
  else if(h < (int)ny){
    int z=GAMin((int)nz,d);
    for(int k=0; k<z; k++)
      for(int j=0; j<h; j++)
	GABinaryString::move(k*h*nx+j*nx,k*ny*nx+j*nx,nx);
  }

  GABinaryString::resize(w*h*d);

  if(w > (int)nx && h > (int)ny){ // adjust the existing bits
    int z=GAMin((int)nz,d);
    for(int k=z-1; k>=0; k--){
      int j;
      for(j=ny-1; j>=0; j--){
	GABinaryString::move(k*h*w+j*w,k*ny*nx+j*nx,nx);
	for(int i=nx; i<w; i++)
	  bit(k*h*w+j*w+i, GARandomBit());
      }
      for(j=ny; j<h; j++)
	for(int i=0; i<w; i++)
	  bit(k*h*w+j*w+i, GARandomBit());
    }
  }
  else if(w > (int)nx){
    int z=GAMin((int)nz,d);
    for(int k=z-1; k>=0; k--){
      for(int j=h-1; j>=0; j--){
	GABinaryString::move(k*h*w+j*w,k*h*nx+j*nx,nx);
	for(int i=nx; i<w; i++)
	  bit(k*h*w+j*w+i, GARandomBit());
      }
    }
  }
  else if(h > (int)ny){
    int z=GAMin((int)nz,d);
    for(int k=z-1; k>=0; k--){
      int j;
      for(j=ny-1; j>=0; j--)
	GABinaryString::move(k*h*w+j*w,k*ny*w+j*w,w);
      for(j=ny; j<h; j++)
	for(int i=0; i<w; i++)
	  bit(k*h*w+j*w+i, GARandomBit());
    }
  }
  if(d > (int)nz){		// change in depth is always new bits
    for(int i=w*h*nz; i<w*h*d; i++)
      bit(i, GARandomBit());
  }

  nx = w; ny = h; nz = d;
  _evaluated = gaFalse;
  return sz;
}
void GeneticOperators::Initializer(GAGenome& g)//todo: better initializer
{
	std::cout<<"calling Initializer\n";
	GAListGenome<Gene>& genome = (GAListGenome<Gene>&)g;


	if(_seedOriginalPosition){
	    while(genome.head()) genome.destroy(); // destroy any pre-existing list
	    for(std::vector<SparCraft::Unit>::const_iterator it=_buildings.begin();
	                   it!=_buildings.end();it++){
	        Gene gene(it->type(),BWAPI::TilePosition((it->pos().x()-it->type().dimensionLeft())/TILE_SIZE,(it->pos().y()-it->type().dimensionUp())/TILE_SIZE));
	        genome.insert(gene,GAListBASE::TAIL);
	    }
	    if(!isLegal(genome)||!isPowered(genome)){
	        std::cout<<"Repairing setup from file"<<std::endl;
	        if(!GeneticOperators::repair(genome)){
	            System::FatalError("Couldn't repair at initializer");
	        }
	    }
	    _seedOriginalPosition=false;
	}else{
	    do{
	        while(genome.head()) genome.destroy(); // destroy any pre-existing list
	        bool needsRepair=false;
	        for(std::vector<SparCraft::Unit>::const_iterator it=_buildings.begin();
	                it!=_buildings.end();it++){


	            BWAPI::TilePosition pos(_defendPlayer->getGoal().x()/TILE_SIZE,_defendPlayer->getGoal().y()/TILE_SIZE);
	            Gene gene(it->type(),pos);
	            //	        BWAPI::TilePosition offset(0,0);
	            int n=placementRetries;
	            do{
	                do{
	                    //	                gene.undo(offset);
	                    //	                offset=BWAPI::TilePosition(GARandomInt(-mutDistance,mutDistance),GARandomInt(-mutDistance,mutDistance));
	                    //	                gene.move(offset);
	                    gene.setPosition(BWAPI::TilePosition(
	                            GARandomInt(_baseLeft,_baseRight),
	                            GARandomInt(_baseTop,_baseBottom)));

	                }while(!_map->canBuildHere(gene.getType(),gene.getCenterPos()));

	                if(isLegal(genome,gene)){
	                    if(!gene.getType().requiresPsi()||isPowered(genome,gene)){
	                        genome.insert(gene,GAListBASE::TAIL);
	                        break;
	                    }
	                }
	                n--;
	            }while(n>0);
	            if(n==0){//if we reached the max amount of tries, add it anyway and try to repair later
	                genome.insert(gene,GAListBASE::TAIL);
	                needsRepair=true;
	                std::cout<<"Max amount of retries for initial location failed, will try to repair\n";
	            }

	            //		std::cout<<"building added"<<std::endl;
	        }
	        if(needsRepair||!isLegal(genome)){
	            if(!GeneticOperators::repair(genome)){
	                System::FatalError("Couldn't repair at initializer");
	            }
	        }
	    }while(!isLegal(genome));
	}
	//	Mutator(genome,0.5,20);
}
Exemple #26
0
void
GADCrowdingGA::step() {
  if(pop->size() == 0) return;

  GAGenome *child = pop->individual(0).clone();

  GAList<int> indpool;

  for (int i=0; i<pop->size(); i++)
    indpool.insert(i);

  do {
    int *ip;
    indpool.warp(GARandomInt(0,indpool.size()-1)); // select mom
    ip=indpool.remove();
    GAGenome *mom = &pop->individual(*ip);
    delete ip;

    indpool.warp(GARandomInt(0,indpool.size()-1)); // select dad
    ip=indpool.remove();
    GAGenome *dad = &pop->individual(*ip);
    delete ip;

    stats.numsel += 2;		                   // create child
    stats.numcro += (*scross)(*mom, *dad, child, 0);
    stats.nummut += child->mutate(pMutation());
    stats.numeval += 1;

    double d1 = child->compare(*mom);      // replace closest parent
    double d2 = child->compare(*dad);
    if (d1 < d2) {
      if (minmax == MINIMIZE) {
    if (child->score() < mom->score()) {
      mom->copy(*child);
      stats.numrep += 1;
    }
      }
      else {
    if (child->score() > mom->score()) {
      mom->copy(*child);
      stats.numrep += 1;
    }
      }
    }
    else {
      if (minmax == MINIMIZE) {
    if (child->score() < dad->score()) {
      dad->copy(*child);
      stats.numrep += 1;
    }
      }
      else {
    if (child->score() > dad->score()) {
      dad->copy(*child);
      stats.numrep += 1;
    }
      }
    }
  } while (indpool.size()>1);

  pop->evaluate(gaTrue);
  stats.update(*pop);

  delete child;
}