1 /*------------------------------------------------------------------------
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 *-------------------------------------------------------------------------
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 -- */
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
);
39 * allocates memory for GA pool
42 alloc_pool(PlannerInfo
*root
, int pool_size
, int string_length
)
49 new_pool
= (Pool
*) palloc(sizeof(Pool
));
50 new_pool
->size
= (int) pool_size
;
51 new_pool
->string_length
= (int) string_length
;
54 new_pool
->data
= (Chromosome
*) palloc(pool_size
* sizeof(Chromosome
));
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
));
66 * deallocates memory for GA pool
69 free_pool(PlannerInfo
*root
, Pool
*pool
)
75 chromo
= (Chromosome
*) pool
->data
; /* vector of all chromos */
76 for (i
= 0; i
< pool
->size
; i
++)
77 pfree(chromo
[i
].string
);
88 * initialize genetic pool
91 random_init_pool(PlannerInfo
*root
, Pool
*pool
)
93 Chromosome
*chromo
= (Chromosome
*) pool
->data
;
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.
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
)
116 if (i
== 0 && bad
>= 10000)
117 elog(ERROR
, "geqo failed to make a valid plan");
123 elog(DEBUG1
, "%d invalid tours found while selecting %d pool entries",
130 * sorts input pool according to worth, from smallest to largest
132 * maybe you have to change compare() for different ordering ...
135 sort_pool(PlannerInfo
*root
, Pool
*pool
)
137 qsort(pool
->data
, pool
->size
, sizeof(Chromosome
), compare
);
142 * qsort comparison function for sort_pool
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
)
152 else if (chromo1
->worth
> chromo2
->worth
)
159 * allocates a chromosome and string space
162 alloc_chromo(PlannerInfo
*root
, int string_length
)
166 chromo
= (Chromosome
*) palloc(sizeof(Chromosome
));
167 chromo
->string
= (Gene
*) palloc((string_length
+ 1) * sizeof(Gene
));
173 * deallocates a chromosome and string space
176 free_chromo(PlannerInfo
*root
, Chromosome
*chromo
)
178 pfree(chromo
->string
);
183 * inserts a new chromosome into the pool, displacing worst gene in pool
184 * assumes best->worst = smallest->largest
187 spread_chromo(PlannerInfo
*root
, Chromosome
*chromo
, Pool
*pool
)
194 Chromosome swap_chromo
,
197 /* new chromo is so bad we can't use it */
198 if (chromo
->worth
> pool
->data
[pool
->size
- 1].worth
)
201 /* do a binary search to find the index of the new chromo */
204 mid
= pool
->size
/ 2;
205 bot
= pool
->size
- 1;
210 /* these 4 cases find a new location */
212 if (chromo
->worth
<= pool
->data
[top
].worth
)
214 else if (chromo
->worth
== pool
->data
[mid
].worth
)
216 else if (chromo
->worth
== pool
->data
[bot
].worth
)
218 else if (bot
- top
<= 1)
223 * these 2 cases move the search indices since a new location has not
227 else if (chromo
->worth
< pool
->data
[mid
].worth
)
230 mid
= top
+ ((bot
- top
) / 2);
233 { /* (chromo->worth > pool->data[mid].worth) */
235 mid
= top
+ ((bot
- top
) / 2);
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
;