aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/geqo/geqo_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/geqo/geqo_main.c')
-rw-r--r--src/backend/optimizer/geqo/geqo_main.c116
1 files changed, 66 insertions, 50 deletions
diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c
index 6a883fa3137..caba3b593f8 100644
--- a/src/backend/optimizer/geqo/geqo_main.c
+++ b/src/backend/optimizer/geqo/geqo_main.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, 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.42 2004/01/21 23:33:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.43 2004/01/23 23:54:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,9 +37,9 @@
/*
* Configuration options
*/
+int Geqo_effort;
int Geqo_pool_size;
int Geqo_generations;
-int Geqo_effort;
double Geqo_selection_bias;
@@ -66,6 +66,7 @@ static int gimme_number_generations(int pool_size);
RelOptInfo *
geqo(Query *root, int number_of_rels, List *initial_rels)
{
+ GeqoEvalData evaldata;
int generation;
Chromosome *momma;
Chromosome *daddy;
@@ -90,6 +91,10 @@ geqo(Query *root, int number_of_rels, List *initial_rels)
int mutations = 0;
#endif
+/* set up evaldata */
+ evaldata.root = root;
+ evaldata.initial_rels = initial_rels;
+
/* set GA parameters */
pool_size = gimme_pool_size(number_of_rels);
number_generations = gimme_number_generations(pool_size);
@@ -99,7 +104,7 @@ geqo(Query *root, int number_of_rels, List *initial_rels)
pool = alloc_pool(pool_size, number_of_rels);
/* random initialization of the pool */
- random_init_pool(root, initial_rels, pool, 0, pool->size);
+ random_init_pool(pool, &evaldata);
/* sort the pool according to cheapest path as fitness */
sort_pool(pool); /* we have to do it only one time, since
@@ -107,41 +112,54 @@ geqo(Query *root, int number_of_rels, List *initial_rels)
* in future (-> geqo_pool.c:spread_chromo
* ) */
+#ifdef GEQO_DEBUG
+ elog(DEBUG1, "GEQO selected %d pool entries, best %.2f, worst %.2f",
+ pool_size,
+ pool->data[0].worth,
+ pool->data[pool_size - 1].worth);
+#endif
+
/* allocate chromosome momma and daddy memory */
momma = alloc_chromo(pool->string_length);
daddy = alloc_chromo(pool->string_length);
#if defined (ERX)
- ereport(DEBUG2,
- (errmsg_internal("using edge recombination crossover [ERX]")));
+#ifdef GEQO_DEBUG
+ elog(DEBUG2, "using edge recombination crossover [ERX]");
+#endif
/* allocate edge table memory */
edge_table = alloc_edge_table(pool->string_length);
#elif defined(PMX)
- ereport(DEBUG2,
- (errmsg_internal("using partially matched crossover [PMX]")));
+#ifdef GEQO_DEBUG
+ elog(DEBUG2, "using partially matched crossover [PMX]");
+#endif
/* allocate chromosome kid memory */
kid = alloc_chromo(pool->string_length);
#elif defined(CX)
- ereport(DEBUG2,
- (errmsg_internal("using cycle crossover [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);
#elif defined(PX)
- ereport(DEBUG2,
- (errmsg_internal("using position crossover [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);
#elif defined(OX1)
- ereport(DEBUG2,
- (errmsg_internal("using order crossover [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);
#elif defined(OX2)
- ereport(DEBUG2,
- (errmsg_internal("using order crossover [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);
@@ -189,8 +207,7 @@ geqo(Query *root, int number_of_rels, List *initial_rels)
/* EVALUATE FITNESS */
- kid->worth = geqo_eval(root, initial_rels,
- kid->string, pool->string_length);
+ kid->worth = geqo_eval(kid->string, pool->string_length, &evaldata);
/* push the kid into the wilderness of life according to its worth */
spread_chromo(kid, pool);
@@ -207,24 +224,28 @@ geqo(Query *root, int number_of_rels, List *initial_rels)
#if defined(ERX) && defined(GEQO_DEBUG)
if (edge_failures != 0)
elog(LOG, "[GEQO] failures: %d, average: %d",
- edge_failures, (int) generation / edge_failures);
+ edge_failures, (int) number_generations / edge_failures);
else
elog(LOG, "[GEQO] no edge failures detected");
#endif
-
#if defined(CX) && defined(GEQO_DEBUG)
if (mutations != 0)
- elog(LOG, "[GEQO] mutations: %d, generations: %d", mutations, generation);
+ elog(LOG, "[GEQO] mutations: %d, generations: %d",
+ mutations, number_generations);
else
elog(LOG, "[GEQO] no mutations processed");
#endif
-
#ifdef GEQO_DEBUG
print_pool(stdout, pool, 0, pool_size - 1);
#endif
+#ifdef GEQO_DEBUG
+ elog(DEBUG1, "GEQO best is %.2f after %d generations",
+ pool->data[0].worth, number_generations);
+#endif
+
/*
* got the cheapest query tree processed by geqo; first element of the
@@ -233,8 +254,7 @@ geqo(Query *root, int number_of_rels, List *initial_rels)
best_tour = (Gene *) pool->data[0].string;
/* root->join_rel_list will be modified during this ! */
- best_rel = gimme_tree(root, initial_rels,
- best_tour, pool->string_length);
+ best_rel = gimme_tree(best_tour, pool->string_length, &evaldata);
if (best_rel == NULL)
elog(ERROR, "failed to make a valid plan");
@@ -272,53 +292,49 @@ geqo(Query *root, int number_of_rels, List *initial_rels)
}
-
/*
- * Return either configured pool size or
- * a good default based on query size (no. of relations)
- * = 2^(QS+1)
- * also constrain between 128 and 1024
+ * Return either configured pool size or a good default
+ *
+ * The default is based on query size (no. of relations) = 2^(QS+1),
+ * but constrained to a range based on the effort value.
*/
static int
gimme_pool_size(int nr_rel)
{
double size;
+ int minsize;
+ int maxsize;
- if (Geqo_pool_size > 0)
+ /* Legal pool size *must* be at least 2, so ignore attempt to select 1 */
+ if (Geqo_pool_size >= 2)
return Geqo_pool_size;
size = pow(2.0, nr_rel + 1.0);
- if (size < MIN_GEQO_POOL_SIZE)
- return MIN_GEQO_POOL_SIZE;
- else if (size > MAX_GEQO_POOL_SIZE)
- return MAX_GEQO_POOL_SIZE;
- else
- return (int) ceil(size);
-}
+ maxsize = 50 * Geqo_effort; /* 50 to 500 individuals */
+ if (size > maxsize)
+ return maxsize;
+ minsize = 10 * Geqo_effort; /* 10 to 100 individuals */
+ if (size < minsize)
+ return minsize;
+
+ return (int) ceil(size);
+}
/*
- * Return either configured number of generations or
- * some reasonable default calculated on the fly.
- * = Effort * Log2(PoolSize)
+ * Return either configured number of generations or a good default
+ *
+ * The default is the same as the pool size, which allows us to be
+ * sure that less-fit individuals get pushed out of the breeding
+ * population before the run finishes.
*/
static int
gimme_number_generations(int pool_size)
{
- double gens;
-
if (Geqo_generations > 0)
return Geqo_generations;
- gens = Geqo_effort * log((double) pool_size) / log(2.0);
-
- /* bound it to a sane range */
- if (gens <= 0)
- gens = 1;
- else if (gens > 10000)
- gens = 10000;
-
- return (int) ceil(gens);
+ return pool_size;
}