Make GEQO's planning deterministic by having it start from a predictable
authorTom Lane <[email protected]>
Thu, 16 Jul 2009 20:55:44 +0000 (20:55 +0000)
committerTom Lane <[email protected]>
Thu, 16 Jul 2009 20:55:44 +0000 (20:55 +0000)
random number seed each time.  This is how it used to work years ago, but
we got rid of the seed reset because it was resetting the main random()
sequence and thus having undesirable effects on the rest of the system.
To fix, establish a private random number state for each execution of
geqo(), and initialize the state using the new GUC variable geqo_seed.
People who want to experiment with different random searches can do so
by changing geqo_seed, but you'll always get the same plan for the same
value of geqo_seed (if holding all other planner inputs constant, of course).

The new state is kept in PlannerInfo by adding a "void *" field reserved
for use by join_search hooks.  Most of the rather bulky code changes in
this commit are just arranging to pass PlannerInfo around to all the GEQO
functions (many of which formerly didn't receive it).

Andres Freund, with some editorialization by Tom

27 files changed:
doc/src/sgml/config.sgml
doc/src/sgml/geqo.sgml
src/backend/optimizer/geqo/Makefile
src/backend/optimizer/geqo/geqo_copy.c
src/backend/optimizer/geqo/geqo_cx.c
src/backend/optimizer/geqo/geqo_erx.c
src/backend/optimizer/geqo/geqo_eval.c
src/backend/optimizer/geqo/geqo_main.c
src/backend/optimizer/geqo/geqo_mutation.c
src/backend/optimizer/geqo/geqo_ox1.c
src/backend/optimizer/geqo/geqo_ox2.c
src/backend/optimizer/geqo/geqo_pmx.c
src/backend/optimizer/geqo/geqo_pool.c
src/backend/optimizer/geqo/geqo_px.c
src/backend/optimizer/geqo/geqo_random.c [new file with mode: 0644]
src/backend/optimizer/geqo/geqo_recombination.c
src/backend/optimizer/geqo/geqo_selection.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/include/nodes/relation.h
src/include/optimizer/geqo.h
src/include/optimizer/geqo_copy.h
src/include/optimizer/geqo_mutation.h
src/include/optimizer/geqo_pool.h
src/include/optimizer/geqo_random.h
src/include/optimizer/geqo_recombination.h
src/include/optimizer/geqo_selection.h

index 99d25d7687464dfa8f0ff764eb0f95f5a2d515fb..89208127b61da17fc4434321b4073638d044c01f 100644 (file)
@@ -2149,7 +2149,23 @@ archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"'  # Windows
        </para>
       </listitem>
      </varlistentry>
-     
+
+     <varlistentry id="guc-geqo-seed" xreflabel="geqo_seed">
+      <term><varname>geqo_seed</varname> (<type>floating point</type>)</term>
+      <indexterm>
+       <primary><varname>geqo_seed</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        Controls the initial value of the random number generator used
+        by GEQO to select random paths through the join order search space.
+        The value can range from zero (the default) to one.  Varying the
+        value changes the set of join paths explored, and may result in a
+        better or worse best path being found.
+       </para>
+      </listitem>
+     </varlistentry>
+
      </variablelist>
     </sect2>
      <sect2 id="runtime-config-query-other">
index 7e03f9b9b59898195601b71f9c44d71a22b2907d..a58fba9693551b67338e2480a45f765e3788b814 100644 (file)
@@ -49,7 +49,7 @@
     methods</firstterm> (e.g., nested loop, hash join, merge join in
     <productname>PostgreSQL</productname>) to process individual joins
     and a diversity of <firstterm>indexes</firstterm> (e.g.,
-    B-tree, hash, GiST and GIN in <productname>PostgreSQL</productname>) as 
+    B-tree, hash, GiST and GIN in <productname>PostgreSQL</productname>) as
     access paths for relations.
    </para>
 
@@ -88,8 +88,7 @@
 
    <para>
     The genetic algorithm (<acronym>GA</acronym>) is a heuristic optimization method which
-    operates through
-    nondeterministic, randomized search. The set of possible solutions for the
+    operates through randomized search. The set of possible solutions for the
     optimization problem is considered as a
     <firstterm>population</firstterm> of <firstterm>individuals</firstterm>.
     The degree of adaptation of an individual to its environment is specified
     According to the <systemitem class="resource">comp.ai.genetic</> <acronym>FAQ</acronym> it cannot be stressed too
     strongly that a <acronym>GA</acronym> is not a pure random search for a solution to a
     problem. A <acronym>GA</acronym> uses stochastic processes, but the result is distinctly
-    non-random (better than random). 
+    non-random (better than random).
    </para>
 
    <figure id="geqo-diagram">
    <para>
     This process is inherently nondeterministic, because of the randomized
     choices made during both the initial population selection and subsequent
-    <quote>mutation</> of the best candidates.  Hence different plans may
-    be selected from one run to the next, resulting in varying run time
-    and varying output row order.
+    <quote>mutation</> of the best candidates.  To avoid surprising changes
+    of the selected plan, each run of the GEQO algorithm restarts its
+    random number generator with the current <xref linkend="guc-geqo-seed">
+    parameter setting.  As long as <varname>geqo_seed</> and the other
+    GEQO parameters are kept fixed, the same plan will be generated for a
+    given query (and other planner inputs such as statistics).  To experiment
+    with different search paths, try changing <varname>geqo_seed</>.
    </para>
 
   </sect2>
       url="news://comp.ai.genetic"></ulink>)
      </para>
     </listitem>
-   
+
     <listitem>
      <para>
       <ulink url="http://www.red3d.com/cwr/evolve.html">
index dbc6c28a32f8fe7dc7d792dc86e5e8fa4d16fa81..9b7f27865c9d36b3ba7a1cc382dec18c21108cdc 100644 (file)
@@ -14,7 +14,7 @@ top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
 OBJS = geqo_copy.o geqo_eval.o geqo_main.o geqo_misc.o \
-       geqo_mutation.o geqo_pool.o geqo_recombination.o \
+       geqo_mutation.o geqo_pool.o geqo_random.o geqo_recombination.o \
        geqo_selection.o \
        geqo_erx.o geqo_pmx.o geqo_cx.o geqo_px.o geqo_ox1.o geqo_ox2.o
 
index 83af33abed8b9a76653fc21c17a08f9092a73632..69f1ceb073e7e88461997dea4c10e5594049018d 100644 (file)
@@ -42,7 +42,8 @@
  *
  */
 void
-geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length)
+geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2,
+                 int string_length)
 {
        int                     i;
 
index 3d5102f6b5bcb00bb3729ddd82f3d17d6d111ae1..0e5cf44838a487c78e777e4d328ce27560008e5d 100644 (file)
@@ -44,7 +44,8 @@
  *      cycle crossover
  */
 int
-cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
+cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring,
+   int num_gene, City *city_table)
 {
 
        int                     i,
@@ -62,7 +63,7 @@ cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
        }
 
        /* choose random cycle starting position */
-       start_pos = geqo_randint(num_gene - 1, 0);
+       start_pos = geqo_randint(root, num_gene - 1, 0);
 
        /* child inherits first city  */
        offspring[start_pos] = tour1[start_pos];
index 35e1a286743301b09f7fdc9f1256719df5a584b8..13ec5cda39ae94cc6395c19f32dfe204cc361da1 100644 (file)
 #include "optimizer/geqo_random.h"
 
 
-static int     gimme_edge(Gene gene1, Gene gene2, Edge *edge_table);
-static void remove_gene(Gene gene, Edge edge, Edge *edge_table);
-static Gene gimme_gene(Edge edge, Edge *edge_table);
+static int     gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table);
+static void remove_gene(PlannerInfo *root, Gene gene, Edge edge, Edge *edge_table);
+static Gene gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table);
 
-static Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene);
+static Gene edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene);
 
 
 /* alloc_edge_table
@@ -50,7 +50,7 @@ static Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene);
  */
 
 Edge *
-alloc_edge_table(int num_gene)
+alloc_edge_table(PlannerInfo *root, int num_gene)
 {
        Edge       *edge_table;
 
@@ -70,7 +70,7 @@ alloc_edge_table(int num_gene)
  *
  */
 void
-free_edge_table(Edge *edge_table)
+free_edge_table(PlannerInfo *root, Edge *edge_table)
 {
        pfree(edge_table);
 }
@@ -89,7 +89,8 @@ free_edge_table(Edge *edge_table)
  *
  */
 float
-gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table)
+gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2,
+                                int num_gene, Edge *edge_table)
 {
        int                     i,
                                index1,
@@ -121,11 +122,11 @@ gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table)
                 * twice per edge
                 */
 
-               edge_total += gimme_edge(tour1[index1], tour1[index2], edge_table);
-               gimme_edge(tour1[index2], tour1[index1], edge_table);
+               edge_total += gimme_edge(root, tour1[index1], tour1[index2], edge_table);
+               gimme_edge(root, tour1[index2], tour1[index1], edge_table);
 
-               edge_total += gimme_edge(tour2[index1], tour2[index2], edge_table);
-               gimme_edge(tour2[index2], tour2[index1], edge_table);
+               edge_total += gimme_edge(root, tour2[index1], tour2[index2], edge_table);
+               gimme_edge(root, tour2[index2], tour2[index1], edge_table);
        }
 
        /* return average number of edges per index */
@@ -147,7 +148,7 @@ gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table)
  *                       0 if edge was already registered and edge_table is unchanged
  */
 static int
-gimme_edge(Gene gene1, Gene gene2, Edge *edge_table)
+gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table)
 {
        int                     i;
        int                     edges;
@@ -189,13 +190,13 @@ gimme_edge(Gene gene1, Gene gene2, Edge *edge_table)
  *
  */
 int
-gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene)
+gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, int num_gene)
 {
        int                     i;
        int                     edge_failures = 0;
 
-       new_gene[0] = (Gene) geqo_randint(num_gene, 1);         /* choose int between 1
-                                                                                                                * and num_gene */
+       /* choose int between 1 and num_gene */
+       new_gene[0] = (Gene) geqo_randint(root, num_gene, 1);
 
        for (i = 1; i < num_gene; i++)
        {
@@ -204,18 +205,18 @@ gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene)
                 * table
                 */
 
-               remove_gene(new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table);
+               remove_gene(root, new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table);
 
                /* find destination for the newly entered point */
 
                if (edge_table[new_gene[i - 1]].unused_edges > 0)
-                       new_gene[i] = gimme_gene(edge_table[(int) new_gene[i - 1]], edge_table);
+                       new_gene[i] = gimme_gene(root, edge_table[(int) new_gene[i - 1]], edge_table);
 
                else
                {                                               /* cope with fault */
                        edge_failures++;
 
-                       new_gene[i] = edge_failure(new_gene, i - 1, edge_table, num_gene);
+                       new_gene[i] = edge_failure(root, new_gene, i - 1, edge_table, num_gene);
                }
 
                /* mark this node as incorporated */
@@ -235,7 +236,7 @@ gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene)
  *
  */
 static void
-remove_gene(Gene gene, Edge edge, Edge *edge_table)
+remove_gene(PlannerInfo *root, Gene gene, Edge edge, Edge *edge_table)
 {
        int                     i,
                                j;
@@ -277,7 +278,7 @@ remove_gene(Gene gene, Edge edge, Edge *edge_table)
  *
  */
 static Gene
-gimme_gene(Edge edge, Edge *edge_table)
+gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table)
 {
        int                     i;
        Gene            friend;
@@ -340,7 +341,7 @@ gimme_gene(Edge edge, Edge *edge_table)
 
 
        /* random decision of the possible candidates to use */
-       rand_decision = (int) geqo_randint(minimum_count - 1, 0);
+       rand_decision = geqo_randint(root, minimum_count - 1, 0);
 
 
        for (i = 0; i < edge.unused_edges; i++)
@@ -368,7 +369,7 @@ gimme_gene(Edge edge, Edge *edge_table)
  *
  */
 static Gene
-edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene)
+edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene)
 {
        int                     i;
        Gene            fail_gene = gene[index];
@@ -401,7 +402,7 @@ edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene)
        if (four_count != 0)
        {
 
-               rand_decision = (int) geqo_randint(four_count - 1, 0);
+               rand_decision = geqo_randint(root, four_count - 1, 0);
 
                for (i = 1; i <= num_gene; i++)
                {
@@ -423,7 +424,7 @@ edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene)
        else if (remaining_edges != 0)
        {
                /* random decision of the gene with remaining edges */
-               rand_decision = (int) geqo_randint(remaining_edges - 1, 0);
+               rand_decision = geqo_randint(root, remaining_edges - 1, 0);
 
                for (i = 1; i <= num_gene; i++)
                {
index 04b3bfe72d5716133fb94255e108a1f3acc6e7b0..c20503b957014c0f23dab60500da4dc4d0ac9bfd 100644 (file)
@@ -42,7 +42,7 @@ static bool desirable_join(PlannerInfo *root,
  * Returns cost of a query tree as an individual of the population.
  */
 Cost
-geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata)
+geqo_eval(PlannerInfo *root, Gene *tour, int num_gene)
 {
        MemoryContext mycontext;
        MemoryContext oldcxt;
@@ -94,13 +94,13 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata)
         * (If we are dealing with enough join rels, which we very likely are, a
         * new hash table will get built and used locally.)
         */
-       savelength = list_length(evaldata->root->join_rel_list);
-       savehash = evaldata->root->join_rel_hash;
+       savelength = list_length(root->join_rel_list);
+       savehash = root->join_rel_hash;
 
-       evaldata->root->join_rel_hash = NULL;
+       root->join_rel_hash = NULL;
 
        /* construct the best path for the given combination of relations */
-       joinrel = gimme_tree(tour, num_gene, evaldata);
+       joinrel = gimme_tree(root, tour, num_gene);
 
        /*
         * compute fitness
@@ -117,9 +117,9 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata)
         * Restore join_rel_list to its former state, and put back original
         * hashtable if any.
         */
-       evaldata->root->join_rel_list = list_truncate(evaldata->root->join_rel_list,
-                                                                                                 savelength);
-       evaldata->root->join_rel_hash = savehash;
+       root->join_rel_list = list_truncate(root->join_rel_list,
+                                                                               savelength);
+       root->join_rel_hash = savehash;
 
        /* release all the memory acquired within gimme_tree */
        MemoryContextSwitchTo(oldcxt);
@@ -134,7 +134,6 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata)
  *       order.
  *
  *      'tour' is the proposed join order, of length 'num_gene'
- *      'evaldata' contains the context we need
  *
  * Returns a new join relation whose cheapest path is the best plan for
  * this join order.  NB: will return NULL if join order is invalid.
@@ -153,8 +152,9 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata)
  * plans.
  */
 RelOptInfo *
-gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata)
+gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
 {
+       GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private;
        RelOptInfo **stack;
        int                     stack_depth;
        RelOptInfo *joinrel;
@@ -193,7 +193,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata)
 
                /* Get the next input relation and push it */
                cur_rel_index = (int) tour[rel_count];
-               stack[stack_depth] = (RelOptInfo *) list_nth(evaldata->initial_rels,
+               stack[stack_depth] = (RelOptInfo *) list_nth(private->initial_rels,
                                                                                                         cur_rel_index - 1);
                stack_depth++;
 
@@ -211,7 +211,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata)
                         * have exhausted the input, the heuristics can't prevent popping.
                         */
                        if (rel_count < num_gene - 1 &&
-                               !desirable_join(evaldata->root, outer_rel, inner_rel))
+                               !desirable_join(root, outer_rel, inner_rel))
                                break;
 
                        /*
@@ -220,7 +220,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata)
                         * root->join_rel_list yet, and so the paths constructed for it
                         * will only include the ones we want.
                         */
-                       joinrel = make_join_rel(evaldata->root, outer_rel, inner_rel);
+                       joinrel = make_join_rel(root, outer_rel, inner_rel);
 
                        /* Can't pop stack here if join order is not valid */
                        if (!joinrel)
index 72b0b5732edb263cfc64445f4dfdb94080cef75e..2453678fc0264fa2abb870c6f273f6f89726ba04 100644 (file)
@@ -27,7 +27,9 @@
 #include <math.h>
 
 #include "optimizer/geqo_misc.h"
+#include "optimizer/geqo_mutation.h"
 #include "optimizer/geqo_pool.h"
+#include "optimizer/geqo_random.h"
 #include "optimizer/geqo_selection.h"
 
 
@@ -38,6 +40,7 @@ int                   Geqo_effort;
 int                    Geqo_pool_size;
 int                    Geqo_generations;
 double         Geqo_selection_bias;
+double         Geqo_seed;
 
 
 static int     gimme_pool_size(int nr_rel);
@@ -63,7 +66,7 @@ static int    gimme_number_generations(int pool_size);
 RelOptInfo *
 geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
 {
-       GeqoEvalData evaldata;
+       GeqoPrivateData private;
        int                     generation;
        Chromosome *momma;
        Chromosome *daddy;
@@ -88,9 +91,12 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
        int                     mutations = 0;
 #endif
 
-/* set up evaldata */
-       evaldata.root = root;
-       evaldata.initial_rels = initial_rels;
+/* set up private information */
+       root->join_search_private = (void *) &private;
+       private.initial_rels = initial_rels;
+
+/* initialize private number generator */
+       geqo_set_seed(root, Geqo_seed);
 
 /* set GA parameters */
        pool_size = gimme_pool_size(number_of_rels);
@@ -98,13 +104,13 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
        status_interval = 10;
 
 /* allocate genetic pool memory */
-       pool = alloc_pool(pool_size, number_of_rels);
+       pool = alloc_pool(root, pool_size, number_of_rels);
 
 /* random initialization of the pool */
-       random_init_pool(pool, &evaldata);
+       random_init_pool(root, pool);
 
 /* sort the pool according to cheapest path as fitness */
-       sort_pool(pool);                        /* we have to do it only one time, since all
+       sort_pool(root, pool);          /* we have to do it only one time, since all
                                                                 * kids replace the worst individuals in
                                                                 * future (-> geqo_pool.c:spread_chromo ) */
 
@@ -116,49 +122,49 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
 #endif
 
 /* allocate chromosome momma and daddy memory */
-       momma = alloc_chromo(pool->string_length);
-       daddy = alloc_chromo(pool->string_length);
+       momma = alloc_chromo(root, pool->string_length);
+       daddy = alloc_chromo(root, pool->string_length);
 
 #if defined (ERX)
 #ifdef GEQO_DEBUG
        elog(DEBUG2, "using edge recombination crossover [ERX]");
 #endif
 /* allocate edge table memory */
-       edge_table = alloc_edge_table(pool->string_length);
+       edge_table = alloc_edge_table(root, pool->string_length);
 #elif defined(PMX)
 #ifdef GEQO_DEBUG
        elog(DEBUG2, "using partially matched crossover [PMX]");
 #endif
 /* allocate chromosome kid memory */
-       kid = alloc_chromo(pool->string_length);
+       kid = alloc_chromo(root, pool->string_length);
 #elif defined(CX)
 #ifdef GEQO_DEBUG
        elog(DEBUG2, "using cycle crossover [CX]");
 #endif
 /* allocate city table memory */
-       kid = alloc_chromo(pool->string_length);
-       city_table = alloc_city_table(pool->string_length);
+       kid = alloc_chromo(root, pool->string_length);
+       city_table = alloc_city_table(root, pool->string_length);
 #elif defined(PX)
 #ifdef GEQO_DEBUG
        elog(DEBUG2, "using position crossover [PX]");
 #endif
 /* allocate city table memory */
-       kid = alloc_chromo(pool->string_length);
-       city_table = alloc_city_table(pool->string_length);
+       kid = alloc_chromo(root, pool->string_length);
+       city_table = alloc_city_table(root, pool->string_length);
 #elif defined(OX1)
 #ifdef GEQO_DEBUG
        elog(DEBUG2, "using order crossover [OX1]");
 #endif
 /* allocate city table memory */
-       kid = alloc_chromo(pool->string_length);
-       city_table = alloc_city_table(pool->string_length);
+       kid = alloc_chromo(root, pool->string_length);
+       city_table = alloc_city_table(root, pool->string_length);
 #elif defined(OX2)
 #ifdef GEQO_DEBUG
        elog(DEBUG2, "using order crossover [OX2]");
 #endif
 /* allocate city table memory */
-       kid = alloc_chromo(pool->string_length);
-       city_table = alloc_city_table(pool->string_length);
+       kid = alloc_chromo(root, pool->string_length);
+       city_table = alloc_city_table(root, pool->string_length);
 #endif
 
 
@@ -168,45 +174,45 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
        for (generation = 0; generation < number_generations; generation++)
        {
                /* SELECTION: using linear bias function */
-               geqo_selection(momma, daddy, pool, Geqo_selection_bias);
+               geqo_selection(root, momma, daddy, pool, Geqo_selection_bias);
 
 #if defined (ERX)
                /* EDGE RECOMBINATION CROSSOVER */
-               difference = gimme_edge_table(momma->string, daddy->string, pool->string_length, edge_table);
+               difference = gimme_edge_table(root, momma->string, daddy->string, pool->string_length, edge_table);
 
                kid = momma;
 
                /* are there any edge failures ? */
-               edge_failures += gimme_tour(edge_table, kid->string, pool->string_length);
+               edge_failures += gimme_tour(root, edge_table, kid->string, pool->string_length);
 #elif defined(PMX)
                /* PARTIALLY MATCHED CROSSOVER */
-               pmx(momma->string, daddy->string, kid->string, pool->string_length);
+               pmx(root, momma->string, daddy->string, kid->string, pool->string_length);
 #elif defined(CX)
                /* CYCLE CROSSOVER */
-               cycle_diffs = cx(momma->string, daddy->string, kid->string, pool->string_length, city_table);
+               cycle_diffs = cx(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
                /* mutate the child */
                if (cycle_diffs == 0)
                {
                        mutations++;
-                       geqo_mutation(kid->string, pool->string_length);
+                       geqo_mutation(root, kid->string, pool->string_length);
                }
 #elif defined(PX)
                /* POSITION CROSSOVER */
-               px(momma->string, daddy->string, kid->string, pool->string_length, city_table);
+               px(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
 #elif defined(OX1)
                /* ORDER CROSSOVER */
-               ox1(momma->string, daddy->string, kid->string, pool->string_length, city_table);
+               ox1(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
 #elif defined(OX2)
                /* ORDER CROSSOVER */
-               ox2(momma->string, daddy->string, kid->string, pool->string_length, city_table);
+               ox2(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
 #endif
 
 
                /* EVALUATE FITNESS */
-               kid->worth = geqo_eval(kid->string, pool->string_length, &evaldata);
+               kid->worth = geqo_eval(root, kid->string, pool->string_length);
 
                /* push the kid into the wilderness of life according to its worth */
-               spread_chromo(kid, pool);
+               spread_chromo(root, kid, pool);
 
 
 #ifdef GEQO_DEBUG
@@ -249,7 +255,7 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
         */
        best_tour = (Gene *) pool->data[0].string;
 
-       best_rel = gimme_tree(best_tour, pool->string_length, &evaldata);
+       best_rel = gimme_tree(root, best_tour, pool->string_length);
 
        if (best_rel == NULL)
                elog(ERROR, "failed to make a valid plan");
@@ -260,28 +266,31 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
 #endif
 
        /* ... free memory stuff */
-       free_chromo(momma);
-       free_chromo(daddy);
+       free_chromo(root, momma);
+       free_chromo(root, daddy);
 
 #if defined (ERX)
-       free_edge_table(edge_table);
+       free_edge_table(root, edge_table);
 #elif defined(PMX)
-       free_chromo(kid);
+       free_chromo(root, kid);
 #elif defined(CX)
-       free_chromo(kid);
-       free_city_table(city_table);
+       free_chromo(root, kid);
+       free_city_table(root, city_table);
 #elif defined(PX)
-       free_chromo(kid);
-       free_city_table(city_table);
+       free_chromo(root, kid);
+       free_city_table(root, city_table);
 #elif defined(OX1)
-       free_chromo(kid);
-       free_city_table(city_table);
+       free_chromo(root, kid);
+       free_city_table(root, city_table);
 #elif defined(OX2)
-       free_chromo(kid);
-       free_city_table(city_table);
+       free_chromo(root, kid);
+       free_city_table(root, city_table);
 #endif
 
-       free_pool(pool);
+       free_pool(root, pool);
+
+       /* ... clear root pointer to our private storage */
+       root->join_search_private = NULL;
 
        return best_rel;
 }
index 899410c42ba47e07543fdbb0f1e9f3707d55043f..acf3b3453437e5231d64acbbbb6dce768b5b088a 100644 (file)
 #include "optimizer/geqo_random.h"
 
 void
-geqo_mutation(Gene *tour, int num_gene)
+geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene)
 {
        int                     swap1;
        int                     swap2;
-       int                     num_swaps = geqo_randint(num_gene / 3, 0);
+       int                     num_swaps = geqo_randint(root, num_gene / 3, 0);
        Gene            temp;
 
 
        while (num_swaps > 0)
        {
-               swap1 = geqo_randint(num_gene - 1, 0);
-               swap2 = geqo_randint(num_gene - 1, 0);
+               swap1 = geqo_randint(root, num_gene - 1, 0);
+               swap2 = geqo_randint(root, num_gene - 1, 0);
 
                while (swap1 == swap2)
-                       swap2 = geqo_randint(num_gene - 1, 0);
+                       swap2 = geqo_randint(root, num_gene - 1, 0);
 
                temp = tour[swap1];
                tour[swap1] = tour[swap2];
index cd979dfa4b6f21bd193d0a2369fd8efb692dee54..3419103d2a22e3541cd57247230ed2e50242c73a 100644 (file)
@@ -43,7 +43,8 @@
  *      position crossover
  */
 void
-ox1(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
+ox1(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene,
+       City *city_table)
 {
        int                     left,
                                right,
@@ -56,8 +57,8 @@ ox1(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
                city_table[k].used = 0;
 
        /* select portion to copy from tour1 */
-       left = geqo_randint(num_gene - 1, 0);
-       right = geqo_randint(num_gene - 1, 0);
+       left = geqo_randint(root, num_gene - 1, 0);
+       right = geqo_randint(root, num_gene - 1, 0);
 
        if (left > right)
        {
index 0d2e0def326b7ba21d66c32dc209ed15667cd955..2526a35ef6b180f729c111e7e858cc18e6c406ec 100644 (file)
@@ -43,7 +43,7 @@
  *      position crossover
  */
 void
-ox2(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
+ox2(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
 {
        int                     k,
                                j,
@@ -60,12 +60,12 @@ ox2(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
        }
 
        /* determine the number of positions to be inherited from tour1  */
-       num_positions = geqo_randint(2 * num_gene / 3, num_gene / 3);
+       num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3);
 
        /* make a list of selected cities */
        for (k = 0; k < num_positions; k++)
        {
-               pos = geqo_randint(num_gene - 1, 0);
+               pos = geqo_randint(root, num_gene - 1, 0);
                city_table[pos].select_list = (int) tour1[pos];
                city_table[(int) tour1[pos]].used = 1;  /* mark used */
        }
index fe9d4b4fc48fc82f5c051475d390a4b9fd0a9a96..5a9a570664f65d61f12b5766bb922d8fc4580dda 100644 (file)
@@ -43,7 +43,7 @@
  *      partially matched crossover
  */
 void
-pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene)
+pmx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene)
 {
        int                *failed = (int *) palloc((num_gene + 1) * sizeof(int));
        int                *from = (int *) palloc((num_gene + 1) * sizeof(int));
@@ -71,8 +71,8 @@ pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene)
        }
 
 /* locate crossover points */
-       left = geqo_randint(num_gene - 1, 0);
-       right = geqo_randint(num_gene - 1, 0);
+       left = geqo_randint(root, num_gene - 1, 0);
+       right = geqo_randint(root, num_gene - 1, 0);
 
        if (left > right)
        {
index 72eb34f3f3a8a56581cb41a9631fceb293a68c02..64e23ba7c129ac1ad27295c0859ee4d44abec45d 100644 (file)
@@ -39,7 +39,7 @@ static int    compare(const void *arg1, const void *arg2);
  *             allocates memory for GA pool
  */
 Pool *
-alloc_pool(int pool_size, int string_length)
+alloc_pool(PlannerInfo *root, int pool_size, int string_length)
 {
        Pool       *new_pool;
        Chromosome *chromo;
@@ -66,7 +66,7 @@ alloc_pool(int pool_size, int string_length)
  *             deallocates memory for GA pool
  */
 void
-free_pool(Pool *pool)
+free_pool(PlannerInfo *root, Pool *pool)
 {
        Chromosome *chromo;
        int                     i;
@@ -88,7 +88,7 @@ free_pool(Pool *pool)
  *             initialize genetic pool
  */
 void
-random_init_pool(Pool *pool, GeqoEvalData *evaldata)
+random_init_pool(PlannerInfo *root, Pool *pool)
 {
        Chromosome *chromo = (Chromosome *) pool->data;
        int                     i;
@@ -105,10 +105,9 @@ random_init_pool(Pool *pool, GeqoEvalData *evaldata)
        i = 0;
        while (i < pool->size)
        {
-               init_tour(chromo[i].string, pool->string_length);
-               pool->data[i].worth = geqo_eval(chromo[i].string,
-                                                                               pool->string_length,
-                                                                               evaldata);
+               init_tour(root, chromo[i].string, pool->string_length);
+               pool->data[i].worth = geqo_eval(root, chromo[i].string,
+                                                                               pool->string_length);
                if (pool->data[i].worth < DBL_MAX)
                        i++;
                else
@@ -133,7 +132,7 @@ random_init_pool(Pool *pool, GeqoEvalData *evaldata)
  *      maybe you have to change compare() for different ordering ...
  */
 void
-sort_pool(Pool *pool)
+sort_pool(PlannerInfo *root, Pool *pool)
 {
        qsort(pool->data, pool->size, sizeof(Chromosome), compare);
 }
@@ -160,7 +159,7 @@ compare(const void *arg1, const void *arg2)
  *       allocates a chromosome and string space
  */
 Chromosome *
-alloc_chromo(int string_length)
+alloc_chromo(PlannerInfo *root, int string_length)
 {
        Chromosome *chromo;
 
@@ -174,7 +173,7 @@ alloc_chromo(int string_length)
  *       deallocates a chromosome and string space
  */
 void
-free_chromo(Chromosome *chromo)
+free_chromo(PlannerInfo *root, Chromosome *chromo)
 {
        pfree(chromo->string);
        pfree(chromo);
@@ -185,7 +184,7 @@ free_chromo(Chromosome *chromo)
  *      assumes best->worst = smallest->largest
  */
 void
-spread_chromo(Chromosome *chromo, Pool *pool)
+spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool)
 {
        int                     top,
                                mid,
@@ -247,7 +246,7 @@ spread_chromo(Chromosome *chromo, Pool *pool)
         * copy new gene into pool storage; always replace worst gene in pool
         */
 
-       geqo_copy(&pool->data[pool->size - 1], chromo, pool->string_length);
+       geqo_copy(root, &pool->data[pool->size - 1], chromo, pool->string_length);
 
        swap_chromo.string = pool->data[pool->size - 1].string;
        swap_chromo.worth = pool->data[pool->size - 1].worth;
index 07f41cd3f425dbe2e03393324236cf55ec2d00b3..958e1bcc8eace91dcb0343e244aeadc5fbbe760f 100644 (file)
@@ -43,7 +43,8 @@
  *      position crossover
  */
 void
-px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
+px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene,
+   City *city_table)
 {
 
        int                     num_positions;
@@ -57,12 +58,12 @@ px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
                city_table[i].used = 0;
 
        /* choose random positions that will be inherited directly from parent */
-       num_positions = geqo_randint(2 * num_gene / 3, num_gene / 3);
+       num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3);
 
        /* choose random position */
        for (i = 0; i < num_positions; i++)
        {
-               pos = geqo_randint(num_gene - 1, 0);
+               pos = geqo_randint(root, num_gene - 1, 0);
 
                offspring[pos] = tour1[pos];    /* transfer cities to child */
                city_table[(int) tour1[pos]].used = 1;  /* mark city used */
diff --git a/src/backend/optimizer/geqo/geqo_random.c b/src/backend/optimizer/geqo/geqo_random.c
new file mode 100644 (file)
index 0000000..5a15c0c
--- /dev/null
@@ -0,0 +1,40 @@
+/*------------------------------------------------------------------------
+ *
+ * geqo_random.c
+ *        random number generator
+ *
+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL$
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "optimizer/geqo_random.h"
+
+
+void
+geqo_set_seed(PlannerInfo *root, double seed)
+{
+       GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private;
+
+       /*
+        * XXX. This seeding algorithm could certainly be improved - but
+        * it is not critical to do so.
+        */
+       memset(private->random_state, 0, sizeof(private->random_state));
+       memcpy(private->random_state,
+                  &seed,
+                  Min(sizeof(private->random_state), sizeof(seed)));
+}
+
+double
+geqo_rand(PlannerInfo *root)
+{
+       GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private;
+
+       return erand48(private->random_state);
+}
index 3972fb141234866b034c5b28fae25874dae3cdb1..c36f3ac6436c1b767055e91adf90a0384a6a11fd 100644 (file)
@@ -35,7 +35,7 @@
  *      and the procedure repeated.
  */
 void
-init_tour(Gene *tour, int num_gene)
+init_tour(PlannerInfo *root, Gene *tour, int num_gene)
 {
        Gene       *tmp;
        int                     remainder;
@@ -53,7 +53,7 @@ init_tour(Gene *tour, int num_gene)
        for (i = 0; i < num_gene; i++)
        {
                /* choose value between 0 and remainder inclusive */
-               next = (int) geqo_randint(remainder, 0);
+               next = geqo_randint(root, remainder, 0);
                /* output that element of the tmp array */
                tour[i] = tmp[next];
                /* and delete it */
@@ -81,7 +81,7 @@ init_tour(Gene *tour, int num_gene)
  *      allocate memory for city table
  */
 City *
-alloc_city_table(int num_gene)
+alloc_city_table(PlannerInfo *root, int num_gene)
 {
        City       *city_table;
 
@@ -99,7 +99,7 @@ alloc_city_table(int num_gene)
  *       deallocate memory of city table
  */
 void
-free_city_table(City *city_table)
+free_city_table(PlannerInfo *root, City *city_table)
 {
        pfree(city_table);
 }
index d4f2c4d5dd7822797dcc9359adb49faaf8fd1abf..8a7e7dcda7c384bfd63f94079eb18f840ddc5561 100644 (file)
@@ -42,7 +42,7 @@
 #include "optimizer/geqo_random.h"
 #include "optimizer/geqo_selection.h"
 
-static int     linear(int max, double bias);
+static int     linear(PlannerInfo *root, int max, double bias);
 
 
 /*
@@ -51,22 +51,23 @@ static int  linear(int max, double bias);
  *      first and second genes are selected from the pool
  */
 void
-geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias)
+geqo_selection(PlannerInfo *root, Chromosome *momma, Chromosome *daddy,
+                          Pool *pool, double bias)
 {
        int                     first,
                                second;
 
-       first = linear(pool->size, bias);
-       second = linear(pool->size, bias);
+       first = linear(root, pool->size, bias);
+       second = linear(root, pool->size, bias);
 
        if (pool->size > 1)
        {
                while (first == second)
-                       second = linear(pool->size, bias);
+                       second = linear(root, pool->size, bias);
        }
 
-       geqo_copy(momma, &pool->data[first], pool->string_length);
-       geqo_copy(daddy, &pool->data[second], pool->string_length);
+       geqo_copy(root, momma, &pool->data[first], pool->string_length);
+       geqo_copy(root, daddy, &pool->data[second], pool->string_length);
 }
 
 /*
@@ -74,12 +75,13 @@ geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias)
  *       generates random integer between 0 and input max number
  *       using input linear bias
  *
+ *       bias is y-intercept of linear distribution
+ *
  *       probability distribution function is: f(x) = bias - 2(bias - 1)x
  *                      bias = (prob of first rule) / (prob of middle rule)
  */
 static int
-linear(int pool_size, double bias)             /* bias is y-intercept of linear
-                                                                                * distribution */
+linear(PlannerInfo *root, int pool_size, double bias)
 {
        double          index;                  /* index between 0 and pop_size */
        double          max = (double) pool_size;
@@ -95,7 +97,7 @@ linear(int pool_size, double bias)            /* bias is y-intercept of linear
        {
                double          sqrtval;
 
-               sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand();
+               sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand(root);
                if (sqrtval > 0.0)
                        sqrtval = sqrt(sqrtval);
                index = max * (bias - sqrtval) / 2.0 / (bias - 1.0);
index bd02ddbe6d3ae9633df7bda19939a5ec2ef85354..8b1c40fcc08bd48acae28c2852048e76adfcd64b 100644 (file)
@@ -2026,6 +2026,14 @@ static struct config_real ConfigureNamesReal[] =
                DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS,
                MAX_GEQO_SELECTION_BIAS, NULL, NULL
        },
+       {
+               {"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
+                       gettext_noop("GEQO: seed for random path selection."),
+                       NULL
+               },
+               &Geqo_seed,
+               0.0, 0.0, 1.0, NULL, NULL
+       },
 
        {
                {"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES,
index c1b888c0d4663088fbd3f40f6949316a5583c13f..e50d7a44f7b839d101ed1384fb1f0ce4972de7d5 100644 (file)
 #geqo_pool_size = 0                    # selects default based on effort
 #geqo_generations = 0                  # selects default based on effort
 #geqo_selection_bias = 2.0             # range 1.5-2.0
+#geqo_seed = 0.0                       # range 0.0-1.0
 
 # - Other Planner Options -
 
index ea4888940345413e2f59821c209887d75dd12728..bbce826e0f705898bc8ef176d0f70dd970b1d36d 100644 (file)
@@ -192,6 +192,9 @@ typedef struct PlannerInfo
        /* These fields are used only when hasRecursion is true: */
        int                     wt_param_id;    /* PARAM_EXEC ID for the work table */
        struct Plan *non_recursive_plan;        /* plan for non-recursive term */
+
+       /* optional private data for join_search_hook, e.g., GEQO */
+       void       *join_search_private;
 } PlannerInfo;
 
 
index ea4c812aae06eaeb447a2c5bc89e83af5e693fa9..d885a68e56043dadcf061f0d364a347399c43f8c 100644 (file)
@@ -46,7 +46,7 @@
 /*
  * Configuration options
  *
- * If you change these, update backend/utils/misc/postgresql.sample.conf
+ * If you change these, update backend/utils/misc/postgresql.conf.sample
  */
 extern int     Geqo_effort;            /* 1 .. 10, knob for adjustment of defaults */
 
@@ -64,16 +64,17 @@ extern double Geqo_selection_bias;
 #define MIN_GEQO_SELECTION_BIAS 1.5
 #define MAX_GEQO_SELECTION_BIAS 2.0
 
+extern double Geqo_seed;               /* 0 .. 1 */
+
 
 /*
- * Data structure to encapsulate information needed for building plan trees
- * (i.e., geqo_eval and gimme_tree).
+ * Private state for a GEQO run --- accessible via root->join_search_private
  */
 typedef struct
 {
-       PlannerInfo *root;                      /* the query we are planning */
-       List       *initial_rels;       /* the base relations */
-} GeqoEvalData;
+       List       *initial_rels;                       /* the base relations we are joining */
+       unsigned short random_state[3];         /* state for erand48() */
+} GeqoPrivateData;
 
 
 /* routines in geqo_main.c */
@@ -81,8 +82,7 @@ extern RelOptInfo *geqo(PlannerInfo *root,
         int number_of_rels, List *initial_rels);
 
 /* routines in geqo_eval.c */
-extern Cost geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata);
-extern RelOptInfo *gimme_tree(Gene *tour, int num_gene,
-                  GeqoEvalData *evaldata);
+extern Cost geqo_eval(PlannerInfo *root, Gene *tour, int num_gene);
+extern RelOptInfo *gimme_tree(PlannerInfo *root, Gene *tour, int num_gene);
 
 #endif   /* GEQO_H */
index ae13059751969599458183b36056fc5b1892a543..d96b969311581037440aef4b4c7c12650eb2a016 100644 (file)
@@ -22,8 +22,9 @@
 #ifndef GEQO_COPY_H
 #define GEQO_COPY_H
 
-#include "optimizer/geqo_gene.h"
+#include "optimizer/geqo.h"
 
-extern void geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length);
+
+extern void geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2, int string_length);
 
 #endif   /* GEQO_COPY_H */
index 0384de8b6fa8bd6f92317ef1145ff85e0fd5d973..c12ee4777d5df35c70ca8b82587dbb8f781d36b9 100644 (file)
@@ -22,8 +22,9 @@
 #ifndef GEQO_MUTATION_H
 #define GEQO_MUTATION_H
 
-#include "optimizer/geqo_gene.h"
+#include "optimizer/geqo.h"
 
-extern void geqo_mutation(Gene *tour, int num_gene);
+
+extern void geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene);
 
 #endif   /* GEQO_MUTATION_H */
index 950e667d61256f20d7a596df318bcd84a963b0bc..dbc6a01831a766aa2425fe202a10080d4110c731 100644 (file)
 #include "optimizer/geqo.h"
 
 
-extern Pool *alloc_pool(int pool_size, int string_length);
-extern void free_pool(Pool *pool);
+extern Pool *alloc_pool(PlannerInfo *root, int pool_size, int string_length);
+extern void free_pool(PlannerInfo *root, Pool *pool);
 
-extern void random_init_pool(Pool *pool, GeqoEvalData *evaldata);
-extern Chromosome *alloc_chromo(int string_length);
-extern void free_chromo(Chromosome *chromo);
+extern void random_init_pool(PlannerInfo *root, Pool *pool);
+extern Chromosome *alloc_chromo(PlannerInfo *root, int string_length);
+extern void free_chromo(PlannerInfo *root, Chromosome *chromo);
 
-extern void spread_chromo(Chromosome *chromo, Pool *pool);
+extern void spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool);
 
-extern void sort_pool(Pool *pool);
+extern void sort_pool(PlannerInfo *root, Pool *pool);
 
 #endif   /* GEQO_POOL_H */
index fab072828f7d39d67601db76d5f7abdf9c8e5322..f24df44b18cab726c37ce33f8b271789ababf423 100644 (file)
 
 #include <math.h>
 
-/* geqo_rand returns a random float value between 0 and 1 inclusive */
+#include "optimizer/geqo.h"
 
-#define geqo_rand() ((double) random() / (double) MAX_RANDOM_VALUE)
 
-/* geqo_randint returns integer value between lower and upper inclusive */
+extern void geqo_set_seed(PlannerInfo *root, double seed);
 
-#define geqo_randint(upper,lower) \
-       ( (int) floor( geqo_rand()*(((upper)-(lower))+0.999999) ) + (lower) )
+/* geqo_rand returns a random float value between 0 and 1 inclusive */
+extern double geqo_rand(PlannerInfo *root);
+
+/* geqo_randint returns integer value between lower and upper inclusive */
+#define geqo_randint(root, upper, lower) \
+       ( (int) floor( geqo_rand(root)*(((upper)-(lower))+0.999999) ) + (lower) )
 
 #endif   /* GEQO_RANDOM_H */
index 2c4a338ca4c069ec46304a0d90cd9b5c8effec63..8feca1105328d587e44826dfaaa883fae0c62f18 100644 (file)
 #ifndef GEQO_RECOMBINATION_H
 #define GEQO_RECOMBINATION_H
 
-#include "optimizer/geqo_gene.h"
+#include "optimizer/geqo.h"
 
-extern void init_tour(Gene *tour, int num_gene);
+
+extern void init_tour(PlannerInfo *root, Gene *tour, int num_gene);
 
 
 /* edge recombination crossover [ERX] */
@@ -38,12 +39,14 @@ typedef struct Edge
        int                     unused_edges;
 } Edge;
 
-extern Edge *alloc_edge_table(int num_gene);
-extern void free_edge_table(Edge *edge_table);
+extern Edge *alloc_edge_table(PlannerInfo *root, int num_gene);
+extern void free_edge_table(PlannerInfo *root, Edge *edge_table);
 
-extern float gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table);
+extern float gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2,
+                                                         int num_gene, Edge *edge_table);
 
-extern int     gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene);
+extern int     gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene,
+                                          int num_gene);
 
 
 /* partially matched crossover [PMX] */
@@ -51,7 +54,9 @@ extern int    gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene);
 #define DAD 1                                  /* indicator for gene from dad */
 #define MOM 0                                  /* indicator for gene from mom */
 
-extern void pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene);
+extern void pmx(PlannerInfo *root,
+                               Gene *tour1, Gene *tour2,
+                               Gene *offspring, int num_gene);
 
 
 typedef struct City
@@ -62,19 +67,23 @@ typedef struct City
        int                     select_list;
 } City;
 
-extern City *alloc_city_table(int num_gene);
-extern void free_city_table(City *city_table);
+extern City *alloc_city_table(PlannerInfo *root, int num_gene);
+extern void free_city_table(PlannerInfo *root, City *city_table);
 
 /* cycle crossover [CX] */
-extern int     cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table);
+extern int     cx(PlannerInfo *root, Gene *tour1, Gene *tour2,
+                          Gene *offspring, int num_gene, City *city_table);
 
 /* position crossover [PX] */
-extern void px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table);
+extern void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring,
+                          int num_gene, City *city_table);
 
 /* order crossover [OX1] according to Davis */
-extern void ox1(Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table);
+extern void ox1(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring,
+                               int num_gene, City *city_table);
 
 /* order crossover [OX2] according to Syswerda */
-extern void ox2(Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table);
+extern void ox2(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring,
+                               int num_gene, City *city_table);
 
 #endif   /* GEQO_RECOMBINATION_H */
index 4b336d13ec1486f62adc3ade689f472f71527339..7177529fddf53af0b42eb1f3bb44cac77cc12a2d 100644 (file)
 #ifndef GEQO_SELECTION_H
 #define GEQO_SELECTION_H
 
-#include "optimizer/geqo_gene.h"
+#include "optimizer/geqo.h"
 
-extern void geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias);
+
+extern void geqo_selection(PlannerInfo *root,
+                                                  Chromosome *momma, Chromosome *daddy,
+                                                  Pool *pool, double bias);
 
 #endif   /* GEQO_SELECTION_H */