⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gapopulation.c

📁 关于遗传算法代码。比较全。希望能给大家带来帮助。
💻 C
📖 第 1 页 / 共 2 页
字号:
// the values of the status members of the object.  So we allow it to work on
// a const population.
void
GAPopulation::scale(GABoolean flag) const {
  if(scaled == gaTrue && flag != gaTrue) return;
  GAPopulation* This = (GAPopulation*)this;

  if(n > 0) {
    sclscm->evaluate(*This);

    float tmpsum;
    This->fitMin = This->fitMax = tmpsum = sind[0]->fitness();
    
    unsigned int i;
    for(i=1; i<n; i++){
      tmpsum += sind[i]->fitness();
      This->fitMax = GAMax(fitMax, sind[i]->fitness());
      This->fitMin = GAMin(fitMin, sind[i]->fitness());
    }
    float tmpave = tmpsum / n;
    This->fitAve = tmpave;
    This->fitSum = tmpsum;	// if scores are huge we'll lose data here

    float tmpvar = 0.0;
    if(n > 1){
      for(i=0; i<n; i++){
	float s = sind[i]->fitness() - This->fitAve;
	s *= s;
	tmpvar += s;
      }
      tmpvar /= (n-1);
    }
    This->fitDev = (float)sqrt(tmpvar);
    This->fitVar = tmpvar;	// could lose data if huge variance
  }
  else {
    This->fitMin = This->fitMax = This->fitSum = 0.0;
    This->fitVar = This->fitDev = 0.0;
  }

  This->scaled = gaTrue;
  This->ssorted = gaFalse;
}


// Calculate the population's diversity score.  The matrix is triangular and
// we don't have to calculate the diagonals.  This assumes that div(i,j) is
// the same as div(j,i) (for our purposes this will always be true, but it is
// possible for someone to override some of the individuals in the population
// and not others).
//   For now we keep twice as many diversity numbers as we need.  We need only
// n*(n-1)/2, but I can't seem to figure out an efficient way to map i,j to the
// reduced n*(n-1)/2 set (remember that the diagonals are always 0.0).
//   The diversity of the entire population is just the average of all the
// individual diversities.  So if every individual is completely different from
// all of the others, the population diversity is > 0.  If they are all the
// same, the diversity is 0.0.  We don't count the diagonals for the population
// diversity measure.  0 means minimal diversity means all the same.
void
GAPopulation::diversity(GABoolean flag) const {
  if(divved == gaTrue && flag != gaTrue) return;
  GAPopulation* This = (GAPopulation*)this;

  if(n > 1) {
    if(This->indDiv == 0) This->indDiv = new float[N*N];

    This->popDiv = 0.0;
    for(unsigned int i=0; i<n; i++){
      This->indDiv[i*n+i] = 0.0;
      for(unsigned int j=i+1; j<n; j++){
	This->indDiv[j*n+i] = This->indDiv[i*n+j] =
	  individual(i).compare(individual(j));
	This->popDiv += indDiv[i*n+j];
      }
    }
    This->popDiv /= n*(n-1)/2;
  }
  else {
    This->popDiv = 0.0;
  }

  This->divved = gaTrue;
}


void
GAPopulation::prepselect(GABoolean flag) const {
  if(selectready == gaTrue && flag != gaTrue) return;
  GAPopulation* This = (GAPopulation*)this;
  This->slct->update();
  This->selectready = gaTrue;
}


// Return a reference to the scaling object.
GAScalingScheme &
GAPopulation::scaling(const GAScalingScheme& s){
  delete sclscm;
  sclscm = s.clone();
  scaled = gaFalse;
  return *sclscm;
}


// Return a reference to the selection object.
GASelectionScheme&
GAPopulation::selector(const GASelectionScheme& s) {
  delete slct;
  slct = s.clone();
  slct->assign(*this);
  selectready = gaFalse;
  return *slct;
}



// 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=(GAGenome *)0;
  if(repl == (GAGenome *)0) 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;
}


// Replace the genome o in the population with the genome r.  Return a
// pointer to the original genome, o.  This assumes that o exists in the
// population.   If it does not, we return a NULL.  If the genomes are the
// same, do nothing and return a pointer to the genome.
GAGenome *
GAPopulation::replace(GAGenome * r, GAGenome * o)
{
  GAGenome * orig=(GAGenome *)0;
  if(r == (GAGenome *)0 || o == (GAGenome *)0) return orig;
  if(r == o) return r;
  unsigned int i;
  for(i=0; i<n && rind[i] != o; i++);
  if(i < n) orig = replace(r, i, RAW);
  return orig;
}


//   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=(GAGenome *)0;
  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;
}


//   Remove the specified genome from the population.  If the genome is
// not in the population, we return NULL.  We do a linear search here (yuk for
// large pops, but little else we can do).  The memory used by the genome is
// now the responsibility of the caller.
GAGenome *
GAPopulation::remove(GAGenome * r)
{
  GAGenome * removed=(GAGenome *)0;
  if(r == (GAGenome *)0) return removed;
  unsigned int i;
  for(i=0; i<n && rind[i] != r; i++);
  if(i < n) removed = remove(i, RAW);
  return removed;
}


// Add the specified individual to the population.  We don't update the stats 
// or sort - let those get updated next time they are needed.
//   Notice that it is possible to add individuals to the population that are
// not the same type as the other genomes in the population.  Eventually we 
// probably won't allow this (or at least we'll have to fix things so that the
// behaviour is completely defined).
//   If you invoke the add with a genome reference, the population will make
// a clone of the genome then it owns it from then on.  If you invoke add with
// a genome pointer, then the population does not allocate any memory - it uses
// the memory pointed to by the argument.  So don't trash the genome without
// first letting the population know about the change.  
GAGenome*
GAPopulation::add(const GAGenome& g)
{
  return GAPopulation::add(g.clone());
}

// This one does *not* allocate space for the genome - it uses the one that 
// was passed to us.  So the caller should not free it up or leave it dangling!
// We own it from now on (unless remove is called on it), and the population
// will destroy it when the population destructor is invoked.
GAGenome*
GAPopulation::add(GAGenome* c)
{
  if(c == (GAGenome *)0) return c;
  grow(n+1);
  rind[n] = sind[n] = c;
  if(ga) rind[n]->geneticAlgorithm(*ga);
  n++;

  rsorted = ssorted = gaFalse;	// may or may not be true, but must be sure
  evaluated = scaled = statted = divved = selectready = gaFalse;

  return c;
}


GAGeneticAlgorithm * 
GAPopulation::geneticAlgorithm(GAGeneticAlgorithm& g){
  for(unsigned int i=0; i<n; i++)
    rind[i]->geneticAlgorithm(g);
  return(ga = &g);
}


#ifndef NO_STREAMS
void 
GAPopulation::write(ostream & os, SortBasis basis) const {
  for(unsigned int i=0; i<n; i++){
    if(basis == RAW)
      os << *rind[i] << "\n";
    else
      os << *sind[i] << "\n";
  }
  os << "\n";
}
#endif






void
GAPopulation::QuickSortAscendingRaw(GAGenome **c, int l, int r) {
  int i,j; float v; GAGenome *t;
  if(r > l){
    v = c[r]->score(); i = l-1; j = r;
    for(;;){
      while(c[++i]->score() < v && i <= r);
      while(c[--j]->score() > v && j > 0);
      if(i >= j) break;
      t = c[i]; c[i] = c[j]; c[j] = t;
    }
    t = c[i]; c[i] = c[r]; c[r] = t;
    GAPopulation::QuickSortAscendingRaw(c,l,i-1);
    GAPopulation::QuickSortAscendingRaw(c,i+1,r);
  }
}
void
GAPopulation::QuickSortDescendingRaw(GAGenome **c, int l, int r) {
  int i,j; float v; GAGenome *t;
  if(r > l){
    v = c[r]->score(); i = l-1; j = r;
    for(;;){
      while(c[++i]->score() > v && i <= r);
      while(c[--j]->score() < v && j > 0);
      if(i >= j) break;
      t = c[i]; c[i] = c[j]; c[j] = t;
    }
    t = c[i]; c[i] = c[r]; c[r] = t;
    GAPopulation::QuickSortDescendingRaw(c,l,i-1);
    GAPopulation::QuickSortDescendingRaw(c,i+1,r);
  }
}

void
GAPopulation::QuickSortAscendingScaled(GAGenome **c, int l, int r) {
  int i,j; float v; GAGenome *t;
  if(r > l){
    v = c[r]->fitness(); i = l-1; j = r;
    for(;;){
      while(c[++i]->fitness() < v && i <= r);
      while(c[--j]->fitness() > v && j > 0);
      if(i >= j) break;
      t = c[i]; c[i] = c[j]; c[j] = t;
    }
    t = c[i]; c[i] = c[r]; c[r] = t;
    GAPopulation::QuickSortAscendingScaled(c,l,i-1);
    GAPopulation::QuickSortAscendingScaled(c,i+1,r);
  }
}
void
GAPopulation::QuickSortDescendingScaled(GAGenome **c, int l, int r) {
  int i,j; float v; GAGenome *t;
  if(r > l){
    v = c[r]->fitness(); i = l-1; j = r;
    for(;;){
      while(c[++i]->fitness() > v && i <= r);
      while(c[--j]->fitness() < v && j > 0);
      if(i >= j) break;
      t = c[i]; c[i] = c[j]; c[j] = t;
    }
    t = c[i]; c[i] = c[r]; c[r] = t;
    GAPopulation::QuickSortDescendingScaled(c,l,i-1);
    GAPopulation::QuickSortDescendingScaled(c,i+1,r);
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -