LCOV - differential code coverage report
Current view: top level - src/backend/optimizer/geqo - geqo_main.c (source / functions) Coverage Total Hit UBC GBC GNC CBC DCB
Current: b45a8d7d8b306b43f31a002f1b3f1dddc8defeaf vs 8767b449a3a1e75626dfb08f24da54933171d4c5 Lines: 91.7 % 48 44 4 1 5 38 2
Current Date: 2025-10-28 08:26:42 +0900 Functions: 100.0 % 3 3 1 2
Baseline: lcov-20251028-005825-baseline Branches: 62.5 % 16 10 6 1 2 7
Baseline Date: 2025-10-27 06:37:35 +0000 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 5 5 5
(360..) days: 90.7 % 43 39 4 1 38
Function coverage date bins:
(360..) days: 100.0 % 3 3 1 2
Branch coverage date bins:
(30,360] days: 100.0 % 2 2 2
(360..) days: 57.1 % 14 8 6 1 7

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  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-2025, 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)
                                 33                 :                : #include "optimizer/geqo_mutation.h"
                                 34                 :                : #endif
                                 35                 :                : #include "optimizer/geqo_pool.h"
                                 36                 :                : #include "optimizer/geqo_random.h"
                                 37                 :                : #include "optimizer/geqo_recombination.h"
                                 38                 :                : #include "optimizer/geqo_selection.h"
                                 39                 :                : 
                                 40                 :                : 
                                 41                 :                : /*
                                 42                 :                :  * Configuration options
                                 43                 :                :  */
                                 44                 :                : int         Geqo_effort;
                                 45                 :                : int         Geqo_pool_size;
                                 46                 :                : int         Geqo_generations;
                                 47                 :                : double      Geqo_selection_bias;
                                 48                 :                : double      Geqo_seed;
                                 49                 :                : 
                                 50                 :                : /* GEQO is treated as an in-core planner extension */
                                 51                 :                : int         Geqo_planner_extension_id = -1;
                                 52                 :                : 
                                 53                 :                : static int  gimme_pool_size(int nr_rel);
                                 54                 :                : static int  gimme_number_generations(int pool_size);
                                 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                 :                : 
                                 73                 :                : RelOptInfo *
 7450 tgl@sss.pgh.pa.us          74                 :CBC          21 : geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
                                 75                 :                : {
                                 76                 :                :     GeqoPrivateData private;
                                 77                 :                :     int         generation;
                                 78                 :                :     Chromosome *momma;
                                 79                 :                :     Chromosome *daddy;
                                 80                 :                :     Chromosome *kid;
                                 81                 :                :     Pool       *pool;
                                 82                 :                :     int         pool_size,
                                 83                 :                :                 number_generations;
                                 84                 :                : 
                                 85                 :                : #ifdef GEQO_DEBUG
                                 86                 :                :     int         status_interval;
                                 87                 :                : #endif
                                 88                 :                :     Gene       *best_tour;
                                 89                 :                :     RelOptInfo *best_rel;
                                 90                 :                : 
                                 91                 :                : #if defined(ERX)
                                 92                 :                :     Edge       *edge_table;     /* list of edges */
10277 bruce@momjian.us           93                 :             21 :     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                 :                : 
   69 rhaas@postgresql.org      103         [ +  + ]:GNC          21 :     if (Geqo_planner_extension_id < 0)
                                104                 :              6 :         Geqo_planner_extension_id = GetPlannerExtensionId("geqo");
                                105                 :                : 
                                106                 :                : /* set up private information */
                                107                 :             21 :     SetPlannerInfoExtensionState(root, Geqo_planner_extension_id, &private);
 5948 tgl@sss.pgh.pa.us         108                 :CBC          21 :     private.initial_rels = initial_rels;
                                109                 :                : 
                                110                 :                : /* inform core planner that we may replan */
   69 rhaas@postgresql.org      111                 :GNC          21 :     root->assumeReplanning = true;
                                112                 :                : 
                                113                 :                : /* initialize private number generator */
 5948 tgl@sss.pgh.pa.us         114                 :CBC          21 :     geqo_set_seed(root, Geqo_seed);
                                115                 :                : 
                                116                 :                : /* set GA parameters */
 9281 peter_e@gmx.net           117                 :             21 :     pool_size = gimme_pool_size(number_of_rels);
 7951 tgl@sss.pgh.pa.us         118                 :             21 :     number_generations = gimme_number_generations(pool_size);
                                119                 :                : #ifdef GEQO_DEBUG
                                120                 :                :     status_interval = 10;
                                121                 :                : #endif
                                122                 :                : 
                                123                 :                : /* allocate genetic pool memory */
 5948                           124                 :             21 :     pool = alloc_pool(root, pool_size, number_of_rels);
                                125                 :                : 
                                126                 :                : /* random initialization of the pool */
                                127                 :             21 :     random_init_pool(root, pool);
                                128                 :                : 
                                129                 :                : /* sort the pool according to cheapest path as fitness */
                                130                 :             21 :     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 */
                                142                 :             21 :     momma = alloc_chromo(root, pool->string_length);
                                143                 :             21 :     daddy = alloc_chromo(root, pool->string_length);
                                144                 :                : 
                                145                 :                : #if defined (ERX)
                                146                 :                : #ifdef GEQO_DEBUG
                                147                 :                :     elog(DEBUG2, "using edge recombination crossover [ERX]");
                                148                 :                : #endif
                                149                 :                : /* allocate edge table memory */
                                150                 :             21 :     edge_table = alloc_edge_table(root, pool->string_length);
                                151                 :                : #elif defined(PMX)
                                152                 :                : #ifdef GEQO_DEBUG
                                153                 :                :     elog(DEBUG2, "using partially matched crossover [PMX]");
                                154                 :                : #endif
                                155                 :                : /* allocate chromosome kid memory */
                                156                 :                :     kid = alloc_chromo(root, pool->string_length);
                                157                 :                : #elif defined(CX)
                                158                 :                : #ifdef GEQO_DEBUG
                                159                 :                :     elog(DEBUG2, "using cycle crossover [CX]");
                                160                 :                : #endif
                                161                 :                : /* allocate city table memory */
                                162                 :                :     kid = alloc_chromo(root, pool->string_length);
                                163                 :                :     city_table = alloc_city_table(root, pool->string_length);
                                164                 :                : #elif defined(PX)
                                165                 :                : #ifdef GEQO_DEBUG
                                166                 :                :     elog(DEBUG2, "using position crossover [PX]");
                                167                 :                : #endif
                                168                 :                : /* allocate city table memory */
                                169                 :                :     kid = alloc_chromo(root, pool->string_length);
                                170                 :                :     city_table = alloc_city_table(root, pool->string_length);
                                171                 :                : #elif defined(OX1)
                                172                 :                : #ifdef GEQO_DEBUG
                                173                 :                :     elog(DEBUG2, "using order crossover [OX1]");
                                174                 :                : #endif
                                175                 :                : /* allocate city table memory */
                                176                 :                :     kid = alloc_chromo(root, pool->string_length);
                                177                 :                :     city_table = alloc_city_table(root, pool->string_length);
                                178                 :                : #elif defined(OX2)
                                179                 :                : #ifdef GEQO_DEBUG
                                180                 :                :     elog(DEBUG2, "using order crossover [OX2]");
                                181                 :                : #endif
                                182                 :                : /* allocate city table memory */
                                183                 :                :     kid = alloc_chromo(root, pool->string_length);
                                184                 :                :     city_table = alloc_city_table(root, pool->string_length);
                                185                 :                : #endif
                                186                 :                : 
                                187                 :                : 
                                188                 :                : /* my pain main part: */
                                189                 :                : /* iterative optimization */
                                190                 :                : 
10278 bruce@momjian.us          191         [ +  + ]:           1113 :     for (generation = 0; generation < number_generations; generation++)
                                192                 :                :     {
                                193                 :                :         /* SELECTION: using linear bias function */
 5948 tgl@sss.pgh.pa.us         194                 :           1092 :         geqo_selection(root, momma, daddy, pool, Geqo_selection_bias);
                                195                 :                : 
                                196                 :                : #if defined (ERX)
                                197                 :                :         /* EDGE RECOMBINATION CROSSOVER */
 5314 peter_e@gmx.net           198                 :           1092 :         gimme_edge_table(root, momma->string, daddy->string, pool->string_length, edge_table);
                                199                 :                : 
10278 bruce@momjian.us          200                 :           1092 :         kid = momma;
                                201                 :                : 
                                202                 :                :         /* are there any edge failures ? */
 5948 tgl@sss.pgh.pa.us         203                 :           1092 :         edge_failures += gimme_tour(root, edge_table, kid->string, pool->string_length);
                                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                 :           1092 :         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                 :           1092 :         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",
                                247                 :                :              edge_failures, (int) number_generations / edge_failures);
                                248                 :                :     else
                                249                 :                :         elog(LOG, "[GEQO] no edge failures detected");
                                250                 :                : #else
                                251                 :                :     /* suppress variable-set-but-not-used warnings from some compilers */
                                252                 :                :     (void) edge_failures;
                                253                 :                : #endif
                                254                 :                : #endif
                                255                 :                : 
                                256                 :                : #if defined(CX) && defined(GEQO_DEBUG)
                                257                 :                :     if (mutations != 0)
                                258                 :                :         elog(LOG, "[GEQO] mutations: %d, generations: %d",
                                259                 :                :              mutations, number_generations);
                                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                 :                :      */
10278 bruce@momjian.us          278                 :             21 :     best_tour = (Gene *) pool->data[0].string;
                                279                 :                : 
 5948 tgl@sss.pgh.pa.us         280                 :             21 :     best_rel = gimme_tree(root, best_tour, pool->string_length);
                                281                 :                : 
 3913                           282         [ -  + ]:             21 :     if (best_rel == NULL)
 3913 tgl@sss.pgh.pa.us         283         [ #  # ]:UBC           0 :         elog(ERROR, "geqo failed to make a valid plan");
                                284                 :                : 
                                285                 :                :     /* DBG: show the query plan */
                                286                 :                : #ifdef NOT_USED
                                287                 :                :     print_plan(best_plan, root);
                                288                 :                : #endif
                                289                 :                : 
                                290                 :                :     /* ... free memory stuff */
 5948 tgl@sss.pgh.pa.us         291                 :CBC          21 :     free_chromo(root, momma);
                                292                 :             21 :     free_chromo(root, daddy);
                                293                 :                : 
                                294                 :                : #if defined (ERX)
                                295                 :             21 :     free_edge_table(root, edge_table);
                                296                 :                : #elif defined(PMX)
                                297                 :                :     free_chromo(root, kid);
                                298                 :                : #elif defined(CX)
                                299                 :                :     free_chromo(root, kid);
                                300                 :                :     free_city_table(root, city_table);
                                301                 :                : #elif defined(PX)
                                302                 :                :     free_chromo(root, kid);
                                303                 :                :     free_city_table(root, city_table);
                                304                 :                : #elif defined(OX1)
                                305                 :                :     free_chromo(root, kid);
                                306                 :                :     free_city_table(root, city_table);
                                307                 :                : #elif defined(OX2)
                                308                 :                :     free_chromo(root, kid);
                                309                 :                :     free_city_table(root, city_table);
                                310                 :                : #endif
                                311                 :                : 
                                312                 :             21 :     free_pool(root, pool);
                                313                 :                : 
                                314                 :                :     /* ... clear root pointer to our private storage */
   69 rhaas@postgresql.org      315                 :GNC          21 :     SetPlannerInfoExtensionState(root, Geqo_planner_extension_id, NULL);
                                316                 :                : 
 9919 bruce@momjian.us          317                 :CBC          21 :     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                 :                :  */
                                327                 :                : static int
 9281 peter_e@gmx.net           328                 :             21 : gimme_pool_size(int nr_rel)
                                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 */
 7949 tgl@sss.pgh.pa.us         335         [ -  + ]:             21 :     if (Geqo_pool_size >= 2)
 8501 bruce@momjian.us          336                 :UBC           0 :         return Geqo_pool_size;
                                337                 :                : 
 9281 peter_e@gmx.net           338                 :CBC          21 :     size = pow(2.0, nr_rel + 1.0);
                                339                 :                : 
 7730 bruce@momjian.us          340                 :             21 :     maxsize = 50 * Geqo_effort; /* 50 to 500 individuals */
 7949 tgl@sss.pgh.pa.us         341         [ -  + ]:             21 :     if (size > maxsize)
 7949 tgl@sss.pgh.pa.us         342                 :UBC           0 :         return maxsize;
                                343                 :                : 
 7730 bruce@momjian.us          344                 :CBC          21 :     minsize = 10 * Geqo_effort; /* 10 to 100 individuals */
 7949 tgl@sss.pgh.pa.us         345         [ +  + ]:             21 :     if (size < minsize)
 7949 tgl@sss.pgh.pa.us         346                 :GBC          18 :         return minsize;
                                347                 :                : 
 7949 tgl@sss.pgh.pa.us         348                 :CBC           3 :     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                 :                :  */
                                359                 :                : static int
 7951                           360                 :             21 : gimme_number_generations(int pool_size)
                                361                 :                : {
                                362         [ -  + ]:             21 :     if (Geqo_generations > 0)
 8986 bruce@momjian.us          363                 :UBC           0 :         return Geqo_generations;
                                364                 :                : 
 7949 tgl@sss.pgh.pa.us         365                 :CBC          21 :     return pool_size;
                                366                 :                : }
        

Generated by: LCOV version 2.4-beta