1/*------------------------------------------------------------------------
4 * solution to the query optimization problem
5 * by means of a Genetic Algorithm (GA)
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/optimizer/geqo/geqo_main.c
12 *-------------------------------------------------------------------------
16 =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
17 * Martin Utesch * Institute of Automatic Control *
18 = = University of Mining and Technology =
19 * utesch@aut.tu-freiberg.de * Freiberg, Germany *
20 =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
23/* -- parts of this are adapted from D. Whitley's Genitor algorithm -- */
42 * Configuration options
54/* complain if no recombination mechanism is #define'd */
61#error "must choose one GEQO recombination mechanism in geqo.h"
67 * solution of the query optimization problem
68 * similar to a constrained Traveling Salesman Problem (TSP)
90 Edge *edge_table;
/* list of edges */
91 int edge_failures = 0;
93#if defined(CX) || defined(PX) || defined(OX1) || defined(OX2)
94 City *city_table;
/* list of cities */
101/* set up private information */
102 root->join_search_private = &
private;
103 private.initial_rels = initial_rels;
105/* initialize private number generator */
108/* set GA parameters */
112 status_interval = 10;
115/* allocate genetic pool memory */
118/* random initialization of the pool */
121/* sort the pool according to cheapest path as fitness */
122 sort_pool(
root, pool);
/* we have to do it only one time, since all
123 * kids replace the worst individuals in
124 * future (-> geqo_pool.c:spread_chromo ) */
127 elog(
DEBUG1,
"GEQO selected %d pool entries, best %.2f, worst %.2f",
133/* allocate chromosome momma and daddy memory */
139 elog(
DEBUG2,
"using edge recombination crossover [ERX]");
141/* allocate edge table memory */
145 elog(
DEBUG2,
"using partially matched crossover [PMX]");
147/* allocate chromosome kid memory */
153/* allocate city table memory */
158 elog(
DEBUG2,
"using position crossover [PX]");
160/* allocate city table memory */
167/* allocate city table memory */
174/* allocate city table memory */
180/* my pain main part: */
181/* iterative optimization */
183 for (generation = 0; generation < number_generations; generation++)
185 /* SELECTION: using linear bias function */
189 /* EDGE RECOMBINATION CROSSOVER */
194 /* are there any edge failures ? */
197 /* PARTIALLY MATCHED CROSSOVER */
200 /* CYCLE CROSSOVER */
202 /* mutate the child */
203 if (cycle_diffs == 0)
209 /* POSITION CROSSOVER */
212 /* ORDER CROSSOVER */
215 /* ORDER CROSSOVER */
220 /* EVALUATE FITNESS */
223 /* push the kid into the wilderness of life according to its worth */
228 if (status_interval && !(generation % status_interval))
229 print_gen(
stdout, pool, generation);
236#if defined(GEQO_DEBUG)
237 if (edge_failures != 0)
238 elog(
LOG,
"[GEQO] failures: %d, average: %d",
239 edge_failures, (
int) number_generations / edge_failures);
241 elog(
LOG,
"[GEQO] no edge failures detected");
243 /* suppress variable-set-but-not-used warnings from some compilers */
244 (void) edge_failures;
248#if defined(CX) && defined(GEQO_DEBUG)
250 elog(
LOG,
"[GEQO] mutations: %d, generations: %d",
251 mutations, number_generations);
253 elog(
LOG,
"[GEQO] no mutations processed");
257 print_pool(
stdout, pool, 0, pool_size - 1);
261 elog(
DEBUG1,
"GEQO best is %.2f after %d generations",
262 pool->
data[0].
worth, number_generations);
267 * got the cheapest query tree processed by geqo; first element of the
268 * population indicates the best query tree
274 if (best_rel == NULL)
275 elog(
ERROR,
"geqo failed to make a valid plan");
277 /* DBG: show the query plan */
279 print_plan(best_plan,
root);
282 /* ... free memory stuff */
306 /* ... clear root pointer to our private storage */
307 root->join_search_private = NULL;
314 * Return either configured pool size or a good default
316 * The default is based on query size (no. of relations) = 2^(QS+1),
317 * but constrained to a range based on the effort value.
326 /* Legal pool size *must* be at least 2, so ignore attempt to select 1 */
330 size = pow(2.0, nr_rel + 1.0);
332 maxsize = 50 *
Geqo_effort;
/* 50 to 500 individuals */
336 minsize = 10 *
Geqo_effort;
/* 10 to 100 individuals */
340 return (
int) ceil(size);
345 * Return either configured number of generations or a good default
347 * The default is the same as the pool size, which allows us to be
348 * sure that less-fit individuals get pushed out of the breeding
349 * population before the run finishes.
Edge * alloc_edge_table(PlannerInfo *root, int num_gene)
float gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table)
void free_edge_table(PlannerInfo *root, Edge *edge_table)
int gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, int num_gene)
Cost geqo_eval(PlannerInfo *root, Gene *tour, int num_gene)
RelOptInfo * gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
RelOptInfo * geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
static int gimme_number_generations(int pool_size)
static int gimme_pool_size(int nr_rel)
double Geqo_selection_bias
void geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene)
Pool * alloc_pool(PlannerInfo *root, int pool_size, int string_length)
void sort_pool(PlannerInfo *root, Pool *pool)
void free_chromo(PlannerInfo *root, Chromosome *chromo)
void free_pool(PlannerInfo *root, Pool *pool)
void random_init_pool(PlannerInfo *root, Pool *pool)
void spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool)
Chromosome * alloc_chromo(PlannerInfo *root, int string_length)
void geqo_set_seed(PlannerInfo *root, double seed)
void free_city_table(PlannerInfo *root, City *city_table)
void pmx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene)
City * alloc_city_table(PlannerInfo *root, int num_gene)
void ox1(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table)
int cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
void ox2(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table)
void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
void geqo_selection(PlannerInfo *root, Chromosome *momma, Chromosome *daddy, Pool *pool, double bias)