Make GEQO's planning deterministic by having it start from a predictable

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
This commit is contained in:
Tom Lane 2009-07-16 20:55:44 +00:00
parent c43feefa80
commit f5bc74192d
27 changed files with 305 additions and 202 deletions

View File

@ -1,4 +1,4 @@
<!-- $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>
@ -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">

View File

@ -1,4 +1,4 @@
<!-- $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>
@ -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
@ -116,7 +115,7 @@
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">
@ -260,9 +259,13 @@
<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>
@ -330,7 +333,7 @@
url="news://comp.ai.genetic"></ulink>)
</para>
</listitem>
<listitem>
<para>
<ulink url="http://www.red3d.com/cwr/evolve.html">

View File

@ -5,7 +5,7 @@
#
# 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 $
#
#-------------------------------------------------------------------------
@ -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

View File

@ -5,7 +5,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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;

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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];

View File

@ -3,7 +3,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -36,11 +36,11 @@
#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++)
{

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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)

View File

@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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;
}

View File

@ -4,7 +4,7 @@
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -36,21 +36,21 @@
#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];

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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)
{

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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 */
}

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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)
{

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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;

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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 */

View File

@ -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: 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);
}

View File

@ -3,7 +3,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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);
}

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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);

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* 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 $
*
*--------------------------------------------------------------------
*/
@ -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,

View File

@ -213,6 +213,7 @@
#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 -

View File

@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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;

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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 */

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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 */

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -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 */

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -26,15 +26,15 @@
#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 */

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -26,13 +26,16 @@
#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)
extern void geqo_set_seed(PlannerInfo *root, double seed);
/* 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(upper,lower) \
( (int) floor( geqo_rand()*(((upper)-(lower))+0.999999) ) + (lower) )
#define geqo_randint(root, upper, lower) \
( (int) floor( geqo_rand(root)*(((upper)-(lower))+0.999999) ) + (lower) )
#endif /* GEQO_RANDOM_H */

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -24,9 +24,10 @@
#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 */

View File

@ -6,7 +6,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
@ -23,8 +23,11 @@
#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 */