-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.221 2009/07/03 19:14:25 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.222 2009/07/16 20:55:44 tgl Exp $ -->
<chapter Id="runtime-config">
<title>Server Configuration</title>
</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">
-<!-- $PostgreSQL: pgsql/doc/src/sgml/geqo.sgml,v 1.40 2007/07/21 04:02:41 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/geqo.sgml,v 1.41 2009/07/16 20:55:44 tgl Exp $ -->
<chapter id="geqo">
<chapterinfo>
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>
<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">
#
# Copyright (c) 1994, Regents of the University of California
#
-# $PostgreSQL: pgsql/src/backend/optimizer/geqo/Makefile,v 1.20 2008/02/19 10:30:07 petere Exp $
+# $PostgreSQL: pgsql/src/backend/optimizer/geqo/Makefile,v 1.21 2009/07/16 20:55:44 tgl Exp $
#
#-------------------------------------------------------------------------
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
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_copy.c,v 1.19 2009/01/01 17:23:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_copy.c,v 1.20 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*
*/
void
-geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length)
+geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2,
+ int string_length)
{
int i;
* CX operator according to Oliver et al
* (Proc 2nd Int'l Conf on GA's)
*
-* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_cx.c,v 1.10 2003/11/29 22:39:49 pgsql Exp $
+* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_cx.c,v 1.11 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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,
}
/* 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];
* geqo_erx.c
* edge recombination crossover [ER]
*
-* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_erx.c,v 1.20 2005/10/15 02:49:19 momjian Exp $
+* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_erx.c,v 1.21 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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
*/
Edge *
-alloc_edge_table(int num_gene)
+alloc_edge_table(PlannerInfo *root, int num_gene)
{
Edge *edge_table;
*
*/
void
-free_edge_table(Edge *edge_table)
+free_edge_table(PlannerInfo *root, Edge *edge_table)
{
pfree(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,
* 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 */
* 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;
*
*/
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++)
{
* 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 */
*
*/
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;
*
*/
static Gene
-gimme_gene(Edge edge, Edge *edge_table)
+gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table)
{
int i;
Gene friend;
/* 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++)
*
*/
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];
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++)
{
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++)
{
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.88 2009/01/01 17:23:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.89 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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;
* (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
* 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);
* 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.
* 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;
/* 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++;
* 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;
/*
* 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)
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.56 2009/01/01 17:23:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.57 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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"
int Geqo_pool_size;
int Geqo_generations;
double Geqo_selection_bias;
+double Geqo_seed;
static int gimme_pool_size(int nr_rel);
RelOptInfo *
geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
{
- GeqoEvalData evaldata;
+ GeqoPrivateData private;
int generation;
Chromosome *momma;
Chromosome *daddy;
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);
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 ) */
#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
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
*/
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");
#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;
}
*
* TSP mutation routines
*
-* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_mutation.c,v 1.9 2003/11/29 22:39:49 pgsql Exp $
+* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_mutation.c,v 1.10 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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];
* OX1 operator according to Davis
* (Proc Int'l Joint Conf on AI)
*
-* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_ox1.c,v 1.9 2003/11/29 22:39:49 pgsql Exp $
+* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_ox1.c,v 1.10 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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,
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)
{
* OX2 operator according to Syswerda
* (The Genetic Algorithms Handbook, ed L Davis)
*
-* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_ox2.c,v 1.10 2004/10/07 15:21:52 momjian Exp $
+* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_ox2.c,v 1.11 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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,
}
/* 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 */
}
* PMX operator according to Goldberg & Lingle
* (Proc Int'l Conf on GA's)
*
-* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_pmx.c,v 1.10 2003/11/29 22:39:49 pgsql Exp $
+* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_pmx.c,v 1.11 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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));
}
/* 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)
{
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_pool.c,v 1.33 2009/01/01 17:23:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_pool.c,v 1.34 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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;
* deallocates memory for GA pool
*/
void
-free_pool(Pool *pool)
+free_pool(PlannerInfo *root, Pool *pool)
{
Chromosome *chromo;
int i;
* 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;
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
* 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);
}
* allocates a chromosome and string space
*/
Chromosome *
-alloc_chromo(int string_length)
+alloc_chromo(PlannerInfo *root, int string_length)
{
Chromosome *chromo;
* deallocates a chromosome and string space
*/
void
-free_chromo(Chromosome *chromo)
+free_chromo(PlannerInfo *root, Chromosome *chromo)
{
pfree(chromo->string);
pfree(chromo);
* assumes best->worst = smallest->largest
*/
void
-spread_chromo(Chromosome *chromo, Pool *pool)
+spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool)
{
int top,
mid,
* 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;
* PX operator according to Syswerda
* (The Genetic Algorithms Handbook, L Davis, ed)
*
-* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_px.c,v 1.10 2003/11/29 22:39:49 pgsql Exp $
+* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_px.c,v 1.11 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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;
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 */
--- /dev/null
+/*------------------------------------------------------------------------
+ *
+ * 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: pgsql/src/backend/optimizer/geqo/geqo_random.c,v 1.1 2009/07/16 20:55:44 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#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);
+}
* geqo_recombination.c
* misc recombination procedures
*
-* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_recombination.c,v 1.15 2005/10/15 02:49:19 momjian Exp $
+* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_recombination.c,v 1.16 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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;
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 */
* allocate memory for city table
*/
City *
-alloc_city_table(int num_gene)
+alloc_city_table(PlannerInfo *root, int num_gene)
{
City *city_table;
* deallocate memory of city table
*/
void
-free_city_table(City *city_table)
+free_city_table(PlannerInfo *root, City *city_table)
{
pfree(city_table);
}
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_selection.c,v 1.24 2009/01/01 17:23:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_selection.c,v 1.25 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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);
/*
* 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);
}
/*
* 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;
{
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);
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.507 2009/07/16 06:33:44 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.508 2009/07/16 20:55:44 tgl Exp $
*
*--------------------------------------------------------------------
*/
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,
#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 -
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.173 2009/06/11 14:49:11 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.174 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* 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;
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/geqo.h,v 1.44 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/geqo.h,v 1.45 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* 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 */
#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 */
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 */
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/geqo_copy.h,v 1.21 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/geqo_copy.h,v 1.22 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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 */
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/geqo_mutation.h,v 1.21 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/geqo_mutation.h,v 1.22 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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 */
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/geqo_pool.h,v 1.25 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/geqo_pool.h,v 1.26 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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 */
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/geqo_random.h,v 1.21 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/geqo_random.h,v 1.22 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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 */
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/geqo_recombination.h,v 1.20 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/geqo_recombination.h,v 1.21 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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] */
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] */
#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
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 */
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/geqo_selection.h,v 1.21 2009/01/01 17:24:00 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/geqo_selection.h,v 1.22 2009/07/16 20:55:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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 */