PostgreSQL Source Code git master
Loading...
Searching...
No Matches
geqo_main.c
Go to the documentation of this file.
1/*------------------------------------------------------------------------
2 *
3 * geqo_main.c
4 * solution to the query optimization problem
5 * by means of a Genetic Algorithm (GA)
6 *
7 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 * src/backend/optimizer/geqo/geqo_main.c
11 *
12 *-------------------------------------------------------------------------
13 */
14
15/*
16 * contributed by:
17 * =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
18 * * Martin Utesch * Institute of Automatic Control *
19 * = = University of Mining and Technology =
20 * * utesch@aut.tu-freiberg.de * Freiberg, Germany *
21 * =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
22 */
23
24/* -- parts of this are adapted from D. Whitley's Genitor algorithm -- */
25
26#include "postgres.h"
27
28#include <math.h>
29
30#include "optimizer/geqo.h"
31
32#include "optimizer/geqo_misc.h"
33#if defined(CX)
35#endif
36#include "optimizer/geqo_pool.h"
40
41
42/*
43 * Configuration options
44 */
49double Geqo_seed;
50
51/* GEQO is treated as an in-core planner extension */
53
54static int gimme_pool_size(int nr_rel);
56
57/* complain if no recombination mechanism is #define'd */
58#if !defined(ERX) && \
59 !defined(PMX) && \
60 !defined(CX) && \
61 !defined(PX) && \
62 !defined(OX1) && \
63 !defined(OX2)
64#error "must choose one GEQO recombination mechanism in geqo.h"
65#endif
66
67
68/*
69 * geqo
70 * solution of the query optimization problem
71 * similar to a constrained Traveling Salesman Problem (TSP)
72 */
73
76{
77 GeqoPrivateData private;
78 int generation;
82 Pool *pool;
83 int pool_size,
85
86#ifdef GEQO_DEBUG
88#endif
91
92#if defined(ERX)
93 Edge *edge_table; /* list of edges */
94 int edge_failures = 0;
95#endif
96#if defined(CX) || defined(PX) || defined(OX1) || defined(OX2)
97 City *city_table; /* list of cities */
98#endif
99#if defined(CX)
100 int cycle_diffs = 0;
101 int mutations = 0;
102#endif
103
106
107/* set up private information */
109 private.initial_rels = initial_rels;
110
111/* inform core planner that we may replan */
112 root->assumeReplanning = true;
113
114/* initialize private number generator */
116
117/* set GA parameters */
120#ifdef GEQO_DEBUG
121 status_interval = 10;
122#endif
123
124/* allocate genetic pool memory */
126
127/* random initialization of the pool */
128 random_init_pool(root, pool);
129
130/* sort the pool according to cheapest path as fitness */
131 sort_pool(root, pool); /* we have to do it only one time, since all
132 * kids replace the worst individuals in
133 * future (-> geqo_pool.c:spread_chromo ) */
134
135#ifdef GEQO_DEBUG
136 elog(DEBUG1, "GEQO selected %d pool entries, best %.2f, worst %.2f",
137 pool_size,
138 pool->data[0].worth,
139 pool->data[pool_size - 1].worth);
140#endif
141
142/* allocate chromosome momma and daddy memory */
145
146#if defined (ERX)
147#ifdef GEQO_DEBUG
148 elog(DEBUG2, "using edge recombination crossover [ERX]");
149#endif
150/* allocate edge table memory */
152#elif defined(PMX)
153#ifdef GEQO_DEBUG
154 elog(DEBUG2, "using partially matched crossover [PMX]");
155#endif
156/* allocate chromosome kid memory */
158#elif defined(CX)
159#ifdef GEQO_DEBUG
160 elog(DEBUG2, "using cycle crossover [CX]");
161#endif
162/* allocate city table memory */
165#elif defined(PX)
166#ifdef GEQO_DEBUG
167 elog(DEBUG2, "using position crossover [PX]");
168#endif
169/* allocate city table memory */
172#elif defined(OX1)
173#ifdef GEQO_DEBUG
174 elog(DEBUG2, "using order crossover [OX1]");
175#endif
176/* allocate city table memory */
179#elif defined(OX2)
180#ifdef GEQO_DEBUG
181 elog(DEBUG2, "using order crossover [OX2]");
182#endif
183/* allocate city table memory */
186#endif
187
188
189/* my pain main part: */
190/* iterative optimization */
191
192 for (generation = 0; generation < number_generations; generation++)
193 {
194 /* SELECTION: using linear bias function */
196
197#if defined (ERX)
198 /* EDGE RECOMBINATION CROSSOVER */
199 gimme_edge_table(root, momma->string, daddy->string, pool->string_length, edge_table);
200
201 kid = momma;
202
203 /* are there any edge failures ? */
205#elif defined(PMX)
206 /* PARTIALLY MATCHED CROSSOVER */
207 pmx(root, momma->string, daddy->string, kid->string, pool->string_length);
208#elif defined(CX)
209 /* CYCLE CROSSOVER */
210 cycle_diffs = cx(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
211 /* mutate the child */
212 if (cycle_diffs == 0)
213 {
214 mutations++;
215 geqo_mutation(root, kid->string, pool->string_length);
216 }
217#elif defined(PX)
218 /* POSITION CROSSOVER */
219 px(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
220#elif defined(OX1)
221 /* ORDER CROSSOVER */
222 ox1(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
223#elif defined(OX2)
224 /* ORDER CROSSOVER */
225 ox2(root, momma->string, daddy->string, kid->string, pool->string_length, city_table);
226#endif
227
228
229 /* EVALUATE FITNESS */
230 kid->worth = geqo_eval(root, kid->string, pool->string_length);
231
232 /* push the kid into the wilderness of life according to its worth */
233 spread_chromo(root, kid, pool);
234
235
236#ifdef GEQO_DEBUG
237 if (status_interval && !(generation % status_interval))
238 print_gen(stdout, pool, generation);
239#endif
240
241 }
242
243
244#if defined(ERX)
245#if defined(GEQO_DEBUG)
246 if (edge_failures != 0)
247 elog(LOG, "[GEQO] failures: %d, average: %d",
249 else
250 elog(LOG, "[GEQO] no edge failures detected");
251#else
252 /* suppress variable-set-but-not-used warnings from some compilers */
254#endif
255#endif
256
257#if defined(CX) && defined(GEQO_DEBUG)
258 if (mutations != 0)
259 elog(LOG, "[GEQO] mutations: %d, generations: %d",
261 else
262 elog(LOG, "[GEQO] no mutations processed");
263#endif
264
265#ifdef GEQO_DEBUG
266 print_pool(stdout, pool, 0, pool_size - 1);
267#endif
268
269#ifdef GEQO_DEBUG
270 elog(DEBUG1, "GEQO best is %.2f after %d generations",
271 pool->data[0].worth, number_generations);
272#endif
273
274
275 /*
276 * got the cheapest query tree processed by geqo; first element of the
277 * population indicates the best query tree
278 */
279 best_tour = (Gene *) pool->data[0].string;
280
282
283 if (best_rel == NULL)
284 elog(ERROR, "geqo failed to make a valid plan");
285
286 /* DBG: show the query plan */
287#ifdef NOT_USED
289#endif
290
291 /* ... free memory stuff */
294
295#if defined (ERX)
297#elif defined(PMX)
299#elif defined(CX)
302#elif defined(PX)
305#elif defined(OX1)
308#elif defined(OX2)
311#endif
312
313 free_pool(root, pool);
314
315 /* ... clear root pointer to our private storage */
317
318 return best_rel;
319}
320
321
322/*
323 * Return either configured pool size or a good default
324 *
325 * The default is based on query size (no. of relations) = 2^(QS+1),
326 * but constrained to a range based on the effort value.
327 */
328static int
330{
331 double size;
332 int minsize;
333 int maxsize;
334
335 /* Legal pool size *must* be at least 2, so ignore attempt to select 1 */
336 if (Geqo_pool_size >= 2)
337 return Geqo_pool_size;
338
339 size = pow(2.0, nr_rel + 1.0);
340
341 maxsize = 50 * Geqo_effort; /* 50 to 500 individuals */
342 if (size > maxsize)
343 return maxsize;
344
345 minsize = 10 * Geqo_effort; /* 10 to 100 individuals */
346 if (size < minsize)
347 return minsize;
348
349 return (int) ceil(size);
350}
351
352
353/*
354 * Return either configured number of generations or a good default
355 *
356 * The default is the same as the pool size, which allows us to be
357 * sure that less-fit individuals get pushed out of the breeding
358 * population before the run finishes.
359 */
360static int
362{
363 if (Geqo_generations > 0)
364 return Geqo_generations;
365
366 return pool_size;
367}
#define LOG
Definition elog.h:32
#define DEBUG2
Definition elog.h:30
#define DEBUG1
Definition elog.h:31
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
void SetPlannerInfoExtensionState(PlannerInfo *root, int extension_id, void *opaque)
Definition extendplan.c:113
int GetPlannerExtensionId(const char *extension_name)
Definition extendplan.c:41
Edge * alloc_edge_table(PlannerInfo *root, int num_gene)
Definition geqo_erx.c:58
float gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table)
Definition geqo_erx.c:99
void free_edge_table(PlannerInfo *root, Edge *edge_table)
Definition geqo_erx.c:79
int gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, int num_gene)
Definition geqo_erx.c:202
Cost geqo_eval(PlannerInfo *root, Gene *tour, int num_gene)
Definition geqo_eval.c:57
RelOptInfo * gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
Definition geqo_eval.c:163
int Gene
Definition geqo_gene.h:33
int Geqo_pool_size
Definition geqo_main.c:46
double Geqo_seed
Definition geqo_main.c:49
int Geqo_generations
Definition geqo_main.c:47
int Geqo_planner_extension_id
Definition geqo_main.c:52
RelOptInfo * geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
Definition geqo_main.c:75
static int gimme_number_generations(int pool_size)
Definition geqo_main.c:361
static int gimme_pool_size(int nr_rel)
Definition geqo_main.c:329
int Geqo_effort
Definition geqo_main.c:45
double Geqo_selection_bias
Definition geqo_main.c:48
void geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene)
Pool * alloc_pool(PlannerInfo *root, int pool_size, int string_length)
Definition geqo_pool.c:42
void sort_pool(PlannerInfo *root, Pool *pool)
Definition geqo_pool.c:135
void free_chromo(PlannerInfo *root, Chromosome *chromo)
Definition geqo_pool.c:178
void free_pool(PlannerInfo *root, Pool *pool)
Definition geqo_pool.c:69
void random_init_pool(PlannerInfo *root, Pool *pool)
Definition geqo_pool.c:91
void spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool)
Definition geqo_pool.c:190
Chromosome * alloc_chromo(PlannerInfo *root, int string_length)
Definition geqo_pool.c:163
void geqo_set_seed(PlannerInfo *root, double seed)
Definition geqo_random.c:19
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 *tour1, Gene *tour2, 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 px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table)
void ox2(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)
static int fb(int x)
tree ctl root
Definition radixtree.h:1857
Cost worth
Definition geqo_gene.h:38
Gene * string
Definition geqo_gene.h:37
Definition pg_list.h:54
int string_length
Definition geqo_gene.h:45
Chromosome * data
Definition geqo_gene.h:43