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