[galib] Similar to Example 9 with discrete variable

Peter Jay Salzman p at dirac.org
Mon Nov 26 17:25:59 EST 2007

On Mon 26 Nov 07,  6:57 PM, Sandip Karale <sandipkarale at gmail.com> said:
>    Hi All,
>    I want to find maximum value in the function.
>       y =  - ( x1^2 / x3 ) - ( x3 / x2^2 )
>    with the constraints
>                  -5 <= x1 <= 5
>                  -5 <= x2 <= 5
>    and         x3  =  { 4, 6, 7, 13}
>    I am not getting how to add the phenotype for the discrete variable x3.
>    Thanks,
>    Sandy

Hi Sandy,

I'm very new to GALib, but here's my understanding:

One genome you can use for this problem is the GA1DArrayAlleleGenome<T>,
which can represent allels on a whole bunch of different types of genes
(floats, chars, ints, unsigned, coins/booleans, etc).

Since you're only interested in floats, you should use GARealGenome, which
is a GA1DArrayAlleleGenome specifically for floats only.

A GARealGenome can be made one of two ways:

   1) # of genes "n", an allele set "aSet", ptr to ObjF

      In this case, you tell GALib explicitly how many genes you want (you
      want n of them) and a single allele set, aSet.  The allele set will
      be applied to all n genes.

   2) an array of allele sets "aArr", ptr to ObjF

      In this case, you don't tell GALib explicitly how many genes you want.
      Instead, GALib takes your array of alleles and counts the number of
      elements.  If there are 3 elements of the array, then there will be
      3 genes in your genome.  The first array element will hold the
      allele set for the 1st gene, the 2nd array element will hold the
      allele set for the 2nd gene, and so on.

Given the above, you're forced into wanting to use a GARealGenome, created
with an array of allele sets, rather than a set of alleles.

Note that if x3's bounds were also [-5,5], you WOULD create your genome with:

   GAAlleleSet<float> aSet( -5.0F, -5.0F );
   GARealGenome genome( 3, aSet, objective );

But since x3's bounds are not the same as x1 and x2, you need to create an
allele array and pass the allele array to GARealGenome.  Here's how you'd do
that (the default is "inclusive", not "exclusive"):

   // Create the x3 allele
   GAAlleleSet<float> zA;

   // Create the allele array with 3 genes
   GARealAlleleSetArray alleles;
   alleles.add(-5.0, 5.0);
   alleles.add(-5.0, 5.0);

and that's pretty much it, to my knowledge.  Note that I'm new to GALib, so
all this can be wrong, but I think it at least approximates the truth to
zeroth order.

For my own education, I tried to implement your problem.

The first thing I did was throw it onto Excel.  Unfortunately, I trust Excel
a bit more than GALib at the moment.  I couldn't find a way of making solver
constrain a problem to discrete values, so I set z=k for each run:

x = -8.1E-10
y = 5
z = 4
F  -.16

x = -8.1E-10
y = 5
z = 6
F  -.24

x = -8.1E-10
y = 5
z = 7
F  -.28

x = -8.1E-10
y = 5
z = 13
F  -.52

So clearly, Excel thinks the answer to your problem is:

x = -8.1E-10
y = 5
z = 4
F  -.16

Since that maximizes F (-.16 is the least negative value for your objective

Next I tried to find an answer by hand.  By taking partial derivatives, the
function is maximized when:

   x = 0
   y = infinity
   z = xy

Given the constraint on y, the answer Solver should've given me was:

   x = 0
   y = 5
   z = xy

I'm not sure what to do with z since it's indeterminant (x*y = 5*0), but if
I had to take a guess, this would indicate that z=0, or given your
constraint on z, that z would be as small as possible.  Your smallest
constraint on z is 4, so I think the analytic answer would be:

   x = 0
   y = 5
   z = 4

which is pretty much what Excel's Solver said.

Next I coded something up with GALib.  Here are the results with the
"standard" GALib:

   p at satan$ time 03main

   9.88578e-05 5 4

   real    0m26.531s
   user    0m26.421s
   sys     0m0.009s

It took about 26 seconds to run, and got an answer of {0,5,4}, which is
exactly what I found using both Excel's solver and calculus.

When I ran your problem through my GALibDbl version of the GALib library,
the returned answer was:

   p at satan$ time ./03maindbl

   1.56162e-06 5 4

   real    0m26.848s
   user    0m26.809s
   sys     0m0.009s

Took just as long, but the numerical "zero" is an order of magnitude closer
to actual zero.   :)

At this point, you'd play with population, generation, crossover, and
mutation probabilities to determine whehter x1 is really "zero zero" or
simply just something close to zero.  Basically, you'd look at covergence.

The code I wrote to implement your problem is below (make sure to change
TYPE to float if you're going to use the default GALib library).

Shameless Plug Alert -- Shameless Plug Alert -- Shameless Plug Alert:

   If anyone finds this answer remotely useful, please consider answering my
   or other peoples' questions in the future.  I still have many questions
   about GALib, but would be more than happy to share what I know with other
   people.  I could really really use some GALib using friends to converse
   and share knowledge with.


// Compile with:
//    g++ -Wall -I galibdbl/ -g3 03main.cc -L galibdbl/ -lga -o 03maindbl
// or:
//    g++ -Wall -I galib/ -g3    03main.cc  -L galib/ -lga -o 03main
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cfloat>
#include "ga/ga.h"
#include "ga/std_stream.h"
#define TYPE double

#include "ga/GARealGenome.h"
using namespace std;

TYPE objective(GAGenome &);
void initializer(GAGenome &);

int main( int argc, char *argv[] )
   GAAlleleSet<TYPE> zA;

   GARealAlleleSetArray alleles;
   alleles.add(-5.0, 5.0);
   alleles.add(-5.0, 5.0);

   GARealGenome genome(alleles, objective);

   GASteadyStateGA ga(genome);

   GASigmaTruncationScaling trunc;

   ga.populationSize( 800 );
   ga.nGenerations( 15000 );
   ga.pMutation( .05 );
   ga.pCrossover( .8 );

   ga.set(gaNscoreFilename, "bog.dat");
   ga.evolve( 0 );
   cout << endl << endl << ga.statistics().bestIndividual() << endl << endl;

   return 0;

TYPE objective( GAGenome &g )
   GARealGenome& genome = ( GARealGenome& )g;

   TYPE x = genome.gene(0);
   TYPE y = genome.gene(1);
   TYPE z = genome.gene(2);

   return  - ( x*x / z ) - z /(y*y );

void initializer( GAGenome &g )
   GARealGenome& genome = ( GARealGenome& )g;
   genome.gene(0, 3.1415926);
   genome.gene(1, 3.1415926);
   genome.gene(2, 13);

GPG Fingerprint: B9F1 6CF3 47C4 7CD8 D33E  70A9 A3B9 1945 67EA 951D
Last night I dreamt of 09-f9-11-02-9d-74-e3-5b-d8-41-56-c5-63-56-88-c0

"A mathematician is a machine for converting coffee    p at dirac.org
 into theorems."     -- Paul Erdös                     http://www.dirac.org

More information about the galib mailing list