Problems with gaview (UNIX)

Maureen Rush rushm at robut.niddk.nih.gov
Fri Dec 10 17:05:07 EST 1999


Dear Matt,

I'm working under Linux and need to use the graphical interface
you wrote in gaview.C. I've tried to implement a combination 
of your ex22.C (SharedOverlapGA) with gaview.C and get
the following error message:

gaview.C: In funtion 'int main(int, char **)':
gaview.C:369: no matching function for call to 
  'GAGeneticAlgorithm::crossover (int ()(const GAGenome &, const GAGenome
&, GAGenome *));
/usr/local/include/ga/GABaseGA.h:192: candidates are: 
   GAGeneticAlgorithm::crossover(int (*)(const GAGenome &, GAGenome *))
/usr/local/include/ga/GABaseGA.h:189:
   GAGeneticALgorithm::crossover(int (*)(const GAGenome &, const GAGenome
&, GAGenome *, GAGenome *)

If I remove the crossover command, the error disappears and upon runtime, 
a window pops up with the population initialized, but the population 
cannot evolve (as expected, I suppose).

The crossover function, which only generates one child,
is not accepted. The pertinent parts of the code follow,
where you should note that I changed GARealGenome to GA1DArrayGenome
throughout gaview.C to accommodate future changes. The above errors
are encountered when GARealGenome is left in the code, but not used.

Note that changing GARealGenome to GA1DArrayGenome works when I use 
any of the other of GAs in the code. However, I get the following
message if I remove GARealGenome from the code:
             /usr/local/include/ga/GAAllele.C 219
             GAAlleleSet:allele(unsigned int)
             this method has not been defined

I'm not sure why GARealGenome is needed when it is not used, and i'm
not sure if the two problems are related. Thanks in advance for considering
my problem.

Maureen 

-----------
Maureen Rush, Ph.D.
Mathematics Department, California State University (on sabbatical)
Mathematics Research Branch, NIH, Bethesda, MD (currently)
email: Maureen_Rush at nih.gov
___________


******Portions of code***********

#include <stdio.h>
#include <iostream.h>
#include <math.h>
#include <ga/ga.h>
#include <ga/GA1DArrayGenome.h>
#include <ga/GA1DArrayGenome.C>
#include <ga/GARealGenome.h>
#include <ga/GARealGenome.C>

#ifdef NO_AUTO_INST
#include <ga/GA1DArrayAlleleGenome.C>
#if defined(__GNUG__)
template class GA1DArrayAlleleGenome<float>;
#else
GA1DArrayAlleleGenome<float>;
#endif
#endif

float RealObjective(GAGenome&);
float Bin2DecObjective(GAGenome&);

typedef float (*Function)(float, float);
float Function1(float x, float y);
float Function2(float x, float y);
float Function3(float x, float y);
float Function4(float x, float y);
float Function5(float x, float y);
Function obj[] = { Function1, Function2, Function3, Function4, Function5 };
float minx[] = {-6, -60, -500, -10, -5 };
float maxx[] = { 6,  60,  500, 10, 5 };
float ai[25],bi[25];

/********************* New genetic algorithm class ********************/

int   Mutator(GAGenome&, float);
void  Initializer(GAGenome&);
float Comparator(const GAGenome&, const GAGenome&);
int   Crossover(const GAGenome&, const GAGenome&, GAGenome*);



// Here we define our own genetic algorithm class.  This class is almost the
// same as the steady-state genetic algorithm, but we modify the step method
// (the one that does all the work) so that we do a slightly modified 
// replacement.  We're only going to do a two-parents-make-one-child mating,
// so we define our own crossover and use it rather than the standard one in
// GAlib.

typedef int (*SingleChildCrossover)(const GAGenome&,const GAGenome&,GAGenome*);

class SharedOverlapGA : public GASteadyStateGA {
public:
  GADefineIdentity("SharedOverlapGA", 200);
  SharedOverlapGA(const GAGenome& g) : GASteadyStateGA(g) {}
  virtual ~SharedOverlapGA() {}
  virtual void step();
  SharedOverlapGA & operator++() { step(); return *this; }
  void crossover(SingleChildCrossover func) {crossFunction = func;}
protected:
  SingleChildCrossover crossFunction;
};

// This step method is similar to that of the regular steady-state genetic
// algorithm, but here we generate only one child in a crossover, and we
// do a slightly different type of replacement.  Here we generate the new
// individuals, insert them into the population, force a scaling to occur, 
// then remove the worst individuals.  This is all done based on the scaled
// (fitness) scores, not the raw (objective) scores.

void
SharedOverlapGA::step()
{ 
  int i;
  GAGenome *mom, *dad;

  for(i=0; i<tmpPop->size(); i++){	// takes care of odd population
    mom = &(pop->select());  
    dad = &(pop->select());
    stats.numsel += 2;		// keep track of number of selections
    if(GAFlipCoin(pCrossover()))
      stats.numcro += crossFunction(*mom, *dad, &tmpPop->individual(i));
    else if(GARandomBit()) 
      tmpPop->individual(i).copy(*mom);
    else
      tmpPop->individual(i).copy(*dad);
    stats.nummut += tmpPop->individual(i).mutate(pMutation());
  }

  for(i=0; i<tmpPop->size(); i++)
    pop->add(tmpPop->individual(i));

  pop->evaluate();		// get info about current pop for next time
  pop->scale();			// remind the population to do its scaling

  for(i=0; i<tmpPop->size(); i++)
    pop->destroy(GAPopulation::WORST, GAPopulation::SCALED);

  stats.update(*pop);		// update the statistics by one generation
}








int
main(int argc, char** argv) {
  cout << "Graphic genetic algorithm demonstration program.\n\n";
  cout << "This program understands the standard GAlib and Xt\n";
  cout << "arguments plus the following:\n\n";
  cout << "  function  which function to solve\n";
  cout << "        0   loaf of bread with 4 smooth humps\n";
  cout << "        1   Shekel's foxholes from DeJong\n";
  cout << "        2   Schwefel's nasty function\n";
  cout << "        3   concentric rings (ripple in a pond) (default)\n";
  cout << "        4   ocean waves\n";
  cout << "  ga        specify which genetic algorithm to use\n";
  cout << "        0   incremental genetic algorithm\n";
  cout << "        1   simple genetic algorithm\n";
  cout << "        2   steady-state genetic algorithm (default)\n";
  cout << "        3   deme genetic algorithm\n";
  cout << "        4   shared-overlap genetic algorithm (speciation)\n";
  cout << "  genome    specify which genome to use\n";
/*  cout << "        0   real number genome (default)\n";
 replaced with 1DArrayGenome */
  cout << "        1   binary-to-decimal genome\n";
  cout << "\n";
  cout << endl;

// make the application widget, grab resource, and parse command line

  Widget toplevel = XtAppInitialize(&theAppData.appc, APP_CLASS, 
				    options, XtNumber(options),
				    &argc, argv, fallbacks, (ArgList)NULL, 0);
  XtGetApplicationResources(toplevel, (XtPointer) &theAppData,
                            resources, XtNumber(resources), NULL, 0);

// do some setup for one of the functions

  for (int j=0; j<25; j++) {
    ai[j] = 16 * ((j % 5) -2);
    bi[j] = 16 * ((j / 5) -2);
  }

// Create the appropriate genome and genetic algorithm

  if(theAppData.whichGenome == 1) {
    GABin2DecPhenotype map;
    map.add(31, minx[theAppData.whichFunction],
	    maxx[theAppData.whichFunction]);
    map.add(31, minx[theAppData.whichFunction],
	    maxx[theAppData.whichFunction]);
    theAppData.genome = new GABin2DecGenome(map, Bin2DecObjective);
  }
  else {
    GAAlleleSet<float> alleleset(minx[theAppData.whichFunction], 
			      maxx[theAppData.whichFunction]);
    theAppData.genome = new GA1DArrayAlleleGenome<float>(2, alleleset, RealObjective);
  }

  if(theAppData.whichGA == 0)
    theAppData.ga = new GAIncrementalGA(*theAppData.genome);
  else if(theAppData.whichGA == 1)
    theAppData.ga = new GASimpleGA(*theAppData.genome);
  else if(theAppData.whichGA == 4){
    theAppData.genome->initializer(::Initializer);
    theAppData.genome->mutator(::Mutator);
    theAppData.genome->comparator(::Comparator);
//    theAppData.genome->crossover(::Crossover);
    GASharing share(Comparator);
    theAppData.ga = new SharedOverlapGA(*theAppData.genome);
    theAppData.ga->crossover(Crossover);
    }
  else if(theAppData.whichGA == 3)
    theAppData.ga = new GADemeGA(*theAppData.genome);
  else
    theAppData.ga = new GASteadyStateGA(*theAppData.genome);

// Now set up the genetic algorithm parameters

  theAppData.ga->parameters(SETTINGS_FILE);
  theAppData.ga->parameters(argc, argv);
  theAppData.ga->initialize();

// we don't allow too many populations (due to our color limit)

  if(theAppData.whichGA == 3) {
    int val;
    theAppData.ga->get(gaNnPopulations, &val);
    if(val > MAX_POPS) {
      val = MAX_POPS;
      theAppData.ga->set(gaNnPopulations, val);
      cerr << "this demo limits the number of populations to "<<MAX_POPS<<"\n";
    }
  }


// These are the objective functions for the genomes.  They simply call the
// appropriate function.
float
Bin2DecObjective(GAGenome& g) {
  GABin2DecGenome& genome = (GABin2DecGenome&)g;
  return (obj[theAppData.whichFunction])(genome.phenotype(0),
					 genome.phenotype(1));
}

float
RealObjective(GAGenome& g) {
  GA1DArrayAlleleGenome<float>& genome = (GA1DArrayAlleleGenome<float>&)g;
  return (obj[theAppData.whichFunction])(genome.gene(0), genome.gene(1));
}

/*****************************************************************************/
/* Type:        2D FUNCTION                                                  */
/* Name:        Objective2D_5                                                */
/* Description: Ocean Waves                                                  */
/* Boundaries:  -5 < x < 5                                                   */
/*              -5 < y < 5                                                   */
/* Source:                                                                   */
/*****************************************************************************/
float
Function5(float x, float y) 
{
  float z = sin(x)*cos(y)+1.0;
  return (z);
}

void
Initializer(GAGenome& g)
{
  GA1DArrayAlleleGenome<float>& genome = (GA1DArrayAlleleGenome<float>&)g;
  genome.gene(0, GARandomFloat(-5.0, 5.0));
  genome.gene(1, GARandomFloat(-5.0, 5.0));
}

int
Mutator(GAGenome& g, float pmut)
{
  GA1DArrayAlleleGenome<float>& genome = (GA1DArrayAlleleGenome<float>&)g;
  int nmut = 0;
  if(GAFlipCoin(pmut)){
    genome.gene(0, genome.gene(0) + 
		GARandomFloat() * (GARandomFloat() - GARandomFloat()));
    genome.gene(1, genome.gene(1) + 
		GARandomFloat() * (GARandomFloat() - GARandomFloat()));
    nmut = 1;
  }
  return nmut;
}

int
Crossover(const GAGenome& g1, const GAGenome& g2, GAGenome* c1)
{
  GA1DArrayAlleleGenome<float>& mom = (GA1DArrayAlleleGenome<float>&)g1;
  GA1DArrayAlleleGenome<float>& dad = (GA1DArrayAlleleGenome<float>&)g2;
  GA1DArrayAlleleGenome<float>& child = (GA1DArrayAlleleGenome<float>&)*c1;

  float distance = 0.0, midpoint = 0.0;

  midpoint = (mom.gene(0) + dad.gene(0)) / 2;
  distance = fabs(mom.gene(0) - dad.gene(0));
  child.gene(0, midpoint + distance * (GARandomFloat() - GARandomFloat()));

  midpoint = (mom.gene(1) + dad.gene(1)) / 2;
  distance = fabs(mom.gene(1) - dad.gene(1));
  child.gene(1, midpoint + distance * (GARandomFloat() - GARandomFloat()));
  return 1;
}


// You can change the factor to control how tightly the distance function 
// considers the spacing of two genomes.  Higher numbers will give you a 
// tighter clustering at function peaks.

#define FACTOR 800

float
Comparator(const GAGenome& g1, const GAGenome& g2) 
{
  GA1DArrayAlleleGenome<float>& a = (GA1DArrayAlleleGenome<float>&)g1;
  GA1DArrayAlleleGenome<float>& b = (GA1DArrayAlleleGenome<float>&)g2;

  float xsum = a.gene(0)+b.gene(0);
  float ysum = a.gene(1)+b.gene(1);
  float val= exp( - (xsum-ysum) * (xsum-ysum) / FACTOR);
  if(1-val < 0 || 1-val > 1) cerr << "val: " << val << "\n";
  return 1-val;
}


















More information about the galib mailing list