Update copyright for 2022
[pgsql.git] / src / backend / optimizer / geqo / geqo_pool.c
blob0dfef1fd3c07ef93d8944a13d406fe01836f376a
1 /*------------------------------------------------------------------------
3 * geqo_pool.c
4 * Genetic Algorithm (GA) pool stuff
6 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * src/backend/optimizer/geqo/geqo_pool.c
11 *-------------------------------------------------------------------------
14 /* contributed by:
15 =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
16 * Martin Utesch * Institute of Automatic Control *
17 = = University of Mining and Technology =
18 * utesch@aut.tu-freiberg.de * Freiberg, Germany *
19 =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
22 /* -- parts of this are adapted from D. Whitley's Genitor algorithm -- */
24 #include "postgres.h"
26 #include <float.h>
27 #include <limits.h>
28 #include <math.h>
30 #include "optimizer/geqo_copy.h"
31 #include "optimizer/geqo_pool.h"
32 #include "optimizer/geqo_recombination.h"
35 static int compare(const void *arg1, const void *arg2);
38 * alloc_pool
39 * allocates memory for GA pool
41 Pool *
42 alloc_pool(PlannerInfo *root, int pool_size, int string_length)
44 Pool *new_pool;
45 Chromosome *chromo;
46 int i;
48 /* pool */
49 new_pool = (Pool *) palloc(sizeof(Pool));
50 new_pool->size = (int) pool_size;
51 new_pool->string_length = (int) string_length;
53 /* all chromosome */
54 new_pool->data = (Chromosome *) palloc(pool_size * sizeof(Chromosome));
56 /* all gene */
57 chromo = (Chromosome *) new_pool->data; /* vector of all chromos */
58 for (i = 0; i < pool_size; i++)
59 chromo[i].string = palloc((string_length + 1) * sizeof(Gene));
61 return new_pool;
65 * free_pool
66 * deallocates memory for GA pool
68 void
69 free_pool(PlannerInfo *root, Pool *pool)
71 Chromosome *chromo;
72 int i;
74 /* all gene */
75 chromo = (Chromosome *) pool->data; /* vector of all chromos */
76 for (i = 0; i < pool->size; i++)
77 pfree(chromo[i].string);
79 /* all chromosome */
80 pfree(pool->data);
82 /* pool */
83 pfree(pool);
87 * random_init_pool
88 * initialize genetic pool
90 void
91 random_init_pool(PlannerInfo *root, Pool *pool)
93 Chromosome *chromo = (Chromosome *) pool->data;
94 int i;
95 int bad = 0;
98 * We immediately discard any invalid individuals (those that geqo_eval
99 * returns DBL_MAX for), thereby not wasting pool space on them.
101 * If we fail to make any valid individuals after 10000 tries, give up;
102 * this probably means something is broken, and we shouldn't just let
103 * ourselves get stuck in an infinite loop.
105 i = 0;
106 while (i < pool->size)
108 init_tour(root, chromo[i].string, pool->string_length);
109 pool->data[i].worth = geqo_eval(root, chromo[i].string,
110 pool->string_length);
111 if (pool->data[i].worth < DBL_MAX)
112 i++;
113 else
115 bad++;
116 if (i == 0 && bad >= 10000)
117 elog(ERROR, "geqo failed to make a valid plan");
121 #ifdef GEQO_DEBUG
122 if (bad > 0)
123 elog(DEBUG1, "%d invalid tours found while selecting %d pool entries",
124 bad, pool->size);
125 #endif
129 * sort_pool
130 * sorts input pool according to worth, from smallest to largest
132 * maybe you have to change compare() for different ordering ...
134 void
135 sort_pool(PlannerInfo *root, Pool *pool)
137 qsort(pool->data, pool->size, sizeof(Chromosome), compare);
141 * compare
142 * qsort comparison function for sort_pool
144 static int
145 compare(const void *arg1, const void *arg2)
147 const Chromosome *chromo1 = (const Chromosome *) arg1;
148 const Chromosome *chromo2 = (const Chromosome *) arg2;
150 if (chromo1->worth == chromo2->worth)
151 return 0;
152 else if (chromo1->worth > chromo2->worth)
153 return 1;
154 else
155 return -1;
158 /* alloc_chromo
159 * allocates a chromosome and string space
161 Chromosome *
162 alloc_chromo(PlannerInfo *root, int string_length)
164 Chromosome *chromo;
166 chromo = (Chromosome *) palloc(sizeof(Chromosome));
167 chromo->string = (Gene *) palloc((string_length + 1) * sizeof(Gene));
169 return chromo;
172 /* free_chromo
173 * deallocates a chromosome and string space
175 void
176 free_chromo(PlannerInfo *root, Chromosome *chromo)
178 pfree(chromo->string);
179 pfree(chromo);
182 /* spread_chromo
183 * inserts a new chromosome into the pool, displacing worst gene in pool
184 * assumes best->worst = smallest->largest
186 void
187 spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool)
189 int top,
190 mid,
191 bot;
192 int i,
193 index;
194 Chromosome swap_chromo,
195 tmp_chromo;
197 /* new chromo is so bad we can't use it */
198 if (chromo->worth > pool->data[pool->size - 1].worth)
199 return;
201 /* do a binary search to find the index of the new chromo */
203 top = 0;
204 mid = pool->size / 2;
205 bot = pool->size - 1;
206 index = -1;
208 while (index == -1)
210 /* these 4 cases find a new location */
212 if (chromo->worth <= pool->data[top].worth)
213 index = top;
214 else if (chromo->worth == pool->data[mid].worth)
215 index = mid;
216 else if (chromo->worth == pool->data[bot].worth)
217 index = bot;
218 else if (bot - top <= 1)
219 index = bot;
223 * these 2 cases move the search indices since a new location has not
224 * yet been found.
227 else if (chromo->worth < pool->data[mid].worth)
229 bot = mid;
230 mid = top + ((bot - top) / 2);
232 else
233 { /* (chromo->worth > pool->data[mid].worth) */
234 top = mid;
235 mid = top + ((bot - top) / 2);
237 } /* ... while */
239 /* now we have index for chromo */
242 * move every gene from index on down one position to make room for chromo
246 * copy new gene into pool storage; always replace worst gene in pool
249 geqo_copy(root, &pool->data[pool->size - 1], chromo, pool->string_length);
251 swap_chromo.string = pool->data[pool->size - 1].string;
252 swap_chromo.worth = pool->data[pool->size - 1].worth;
254 for (i = index; i < pool->size; i++)
256 tmp_chromo.string = pool->data[i].string;
257 tmp_chromo.worth = pool->data[i].worth;
259 pool->data[i].string = swap_chromo.string;
260 pool->data[i].worth = swap_chromo.worth;
262 swap_chromo.string = tmp_chromo.string;
263 swap_chromo.worth = tmp_chromo.worth;