From 0619a832b0c8cbd2a3a327618a6c7680a4f3513c Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 16 Jul 2009 20:55:44 +0000 Subject: [PATCH] Make GEQO's planning deterministic by having it start from a predictable random number seed each time. This is how it used to work years ago, but we got rid of the seed reset because it was resetting the main random() sequence and thus having undesirable effects on the rest of the system. To fix, establish a private random number state for each execution of geqo(), and initialize the state using the new GUC variable geqo_seed. People who want to experiment with different random searches can do so by changing geqo_seed, but you'll always get the same plan for the same value of geqo_seed (if holding all other planner inputs constant, of course). The new state is kept in PlannerInfo by adding a "void *" field reserved for use by join_search hooks. Most of the rather bulky code changes in this commit are just arranging to pass PlannerInfo around to all the GEQO functions (many of which formerly didn't receive it). Andres Freund, with some editorialization by Tom --- doc/src/sgml/config.sgml | 18 +++- doc/src/sgml/geqo.sgml | 19 ++-- src/backend/optimizer/geqo/Makefile | 2 +- src/backend/optimizer/geqo/geqo_copy.c | 3 +- src/backend/optimizer/geqo/geqo_cx.c | 5 +- src/backend/optimizer/geqo/geqo_erx.c | 49 +++++----- src/backend/optimizer/geqo/geqo_eval.c | 26 ++--- src/backend/optimizer/geqo/geqo_main.c | 97 ++++++++++--------- src/backend/optimizer/geqo/geqo_mutation.c | 10 +- src/backend/optimizer/geqo/geqo_ox1.c | 7 +- src/backend/optimizer/geqo/geqo_ox2.c | 6 +- src/backend/optimizer/geqo/geqo_pmx.c | 6 +- src/backend/optimizer/geqo/geqo_pool.c | 23 +++-- src/backend/optimizer/geqo/geqo_px.c | 7 +- src/backend/optimizer/geqo/geqo_random.c | 40 ++++++++ .../optimizer/geqo/geqo_recombination.c | 8 +- src/backend/optimizer/geqo/geqo_selection.c | 22 +++-- src/backend/utils/misc/guc.c | 8 ++ src/backend/utils/misc/postgresql.conf.sample | 1 + src/include/nodes/relation.h | 3 + src/include/optimizer/geqo.h | 18 ++-- src/include/optimizer/geqo_copy.h | 5 +- src/include/optimizer/geqo_mutation.h | 5 +- src/include/optimizer/geqo_pool.h | 14 +-- src/include/optimizer/geqo_random.h | 13 ++- src/include/optimizer/geqo_recombination.h | 35 ++++--- src/include/optimizer/geqo_selection.h | 7 +- 27 files changed, 280 insertions(+), 177 deletions(-) create mode 100644 src/backend/optimizer/geqo/geqo_random.c diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 99d25d7687..89208127b6 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -2149,7 +2149,23 @@ archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"' # Windows - + + + geqo_seed (floating point) + + geqo_seed configuration parameter + + + + Controls the initial value of the random number generator used + by GEQO to select random paths through the join order search space. + The value can range from zero (the default) to one. Varying the + value changes the set of join paths explored, and may result in a + better or worse best path being found. + + + + diff --git a/doc/src/sgml/geqo.sgml b/doc/src/sgml/geqo.sgml index 7e03f9b9b5..a58fba9693 100644 --- a/doc/src/sgml/geqo.sgml +++ b/doc/src/sgml/geqo.sgml @@ -49,7 +49,7 @@ methods (e.g., nested loop, hash join, merge join in PostgreSQL) to process individual joins and a diversity of indexes (e.g., - B-tree, hash, GiST and GIN in PostgreSQL) as + B-tree, hash, GiST and GIN in PostgreSQL) as access paths for relations. @@ -88,8 +88,7 @@ The genetic algorithm (GA) is a heuristic optimization method which - operates through - nondeterministic, randomized search. The set of possible solutions for the + operates through randomized search. The set of possible solutions for the optimization problem is considered as a population of individuals. The degree of adaptation of an individual to its environment is specified @@ -116,7 +115,7 @@ According to the comp.ai.genetic FAQ it cannot be stressed too strongly that a GA is not a pure random search for a solution to a problem. A GA uses stochastic processes, but the result is distinctly - non-random (better than random). + non-random (better than random).
@@ -260,9 +259,13 @@ This process is inherently nondeterministic, because of the randomized choices made during both the initial population selection and subsequent - mutation of the best candidates. Hence different plans may - be selected from one run to the next, resulting in varying run time - and varying output row order. + mutation of the best candidates. To avoid surprising changes + of the selected plan, each run of the GEQO algorithm restarts its + random number generator with the current + parameter setting. As long as geqo_seed and the other + GEQO parameters are kept fixed, the same plan will be generated for a + given query (and other planner inputs such as statistics). To experiment + with different search paths, try changing geqo_seed. @@ -330,7 +333,7 @@ url="news://comp.ai.genetic">) - + diff --git a/src/backend/optimizer/geqo/Makefile b/src/backend/optimizer/geqo/Makefile index dbc6c28a32..9b7f27865c 100644 --- a/src/backend/optimizer/geqo/Makefile +++ b/src/backend/optimizer/geqo/Makefile @@ -14,7 +14,7 @@ top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global OBJS = geqo_copy.o geqo_eval.o geqo_main.o geqo_misc.o \ - geqo_mutation.o geqo_pool.o geqo_recombination.o \ + geqo_mutation.o geqo_pool.o geqo_random.o geqo_recombination.o \ geqo_selection.o \ geqo_erx.o geqo_pmx.o geqo_cx.o geqo_px.o geqo_ox1.o geqo_ox2.o diff --git a/src/backend/optimizer/geqo/geqo_copy.c b/src/backend/optimizer/geqo/geqo_copy.c index 83af33abed..69f1ceb073 100644 --- a/src/backend/optimizer/geqo/geqo_copy.c +++ b/src/backend/optimizer/geqo/geqo_copy.c @@ -42,7 +42,8 @@ * */ void -geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length) +geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2, + int string_length) { int i; diff --git a/src/backend/optimizer/geqo/geqo_cx.c b/src/backend/optimizer/geqo/geqo_cx.c index 3d5102f6b5..0e5cf44838 100644 --- a/src/backend/optimizer/geqo/geqo_cx.c +++ b/src/backend/optimizer/geqo/geqo_cx.c @@ -44,7 +44,8 @@ * cycle crossover */ int -cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, + int num_gene, City *city_table) { int i, @@ -62,7 +63,7 @@ cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) } /* choose random cycle starting position */ - start_pos = geqo_randint(num_gene - 1, 0); + start_pos = geqo_randint(root, num_gene - 1, 0); /* child inherits first city */ offspring[start_pos] = tour1[start_pos]; diff --git a/src/backend/optimizer/geqo/geqo_erx.c b/src/backend/optimizer/geqo/geqo_erx.c index 35e1a28674..13ec5cda39 100644 --- a/src/backend/optimizer/geqo/geqo_erx.c +++ b/src/backend/optimizer/geqo/geqo_erx.c @@ -36,11 +36,11 @@ #include "optimizer/geqo_random.h" -static int gimme_edge(Gene gene1, Gene gene2, Edge *edge_table); -static void remove_gene(Gene gene, Edge edge, Edge *edge_table); -static Gene gimme_gene(Edge edge, Edge *edge_table); +static int gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table); +static void remove_gene(PlannerInfo *root, Gene gene, Edge edge, Edge *edge_table); +static Gene gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table); -static Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene); +static Gene edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene); /* alloc_edge_table @@ -50,7 +50,7 @@ static Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene); */ Edge * -alloc_edge_table(int num_gene) +alloc_edge_table(PlannerInfo *root, int num_gene) { Edge *edge_table; @@ -70,7 +70,7 @@ alloc_edge_table(int num_gene) * */ void -free_edge_table(Edge *edge_table) +free_edge_table(PlannerInfo *root, Edge *edge_table) { pfree(edge_table); } @@ -89,7 +89,8 @@ free_edge_table(Edge *edge_table) * */ float -gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table) +gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2, + int num_gene, Edge *edge_table) { int i, index1, @@ -121,11 +122,11 @@ gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table) * twice per edge */ - edge_total += gimme_edge(tour1[index1], tour1[index2], edge_table); - gimme_edge(tour1[index2], tour1[index1], edge_table); + edge_total += gimme_edge(root, tour1[index1], tour1[index2], edge_table); + gimme_edge(root, tour1[index2], tour1[index1], edge_table); - edge_total += gimme_edge(tour2[index1], tour2[index2], edge_table); - gimme_edge(tour2[index2], tour2[index1], edge_table); + edge_total += gimme_edge(root, tour2[index1], tour2[index2], edge_table); + gimme_edge(root, tour2[index2], tour2[index1], edge_table); } /* return average number of edges per index */ @@ -147,7 +148,7 @@ gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table) * 0 if edge was already registered and edge_table is unchanged */ static int -gimme_edge(Gene gene1, Gene gene2, Edge *edge_table) +gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table) { int i; int edges; @@ -189,13 +190,13 @@ gimme_edge(Gene gene1, Gene gene2, Edge *edge_table) * */ int -gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene) +gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, int num_gene) { int i; int edge_failures = 0; - new_gene[0] = (Gene) geqo_randint(num_gene, 1); /* choose int between 1 - * and num_gene */ + /* choose int between 1 and num_gene */ + new_gene[0] = (Gene) geqo_randint(root, num_gene, 1); for (i = 1; i < num_gene; i++) { @@ -204,18 +205,18 @@ gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene) * table */ - remove_gene(new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table); + remove_gene(root, new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table); /* find destination for the newly entered point */ if (edge_table[new_gene[i - 1]].unused_edges > 0) - new_gene[i] = gimme_gene(edge_table[(int) new_gene[i - 1]], edge_table); + new_gene[i] = gimme_gene(root, edge_table[(int) new_gene[i - 1]], edge_table); else { /* cope with fault */ edge_failures++; - new_gene[i] = edge_failure(new_gene, i - 1, edge_table, num_gene); + new_gene[i] = edge_failure(root, new_gene, i - 1, edge_table, num_gene); } /* mark this node as incorporated */ @@ -235,7 +236,7 @@ gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene) * */ static void -remove_gene(Gene gene, Edge edge, Edge *edge_table) +remove_gene(PlannerInfo *root, Gene gene, Edge edge, Edge *edge_table) { int i, j; @@ -277,7 +278,7 @@ remove_gene(Gene gene, Edge edge, Edge *edge_table) * */ static Gene -gimme_gene(Edge edge, Edge *edge_table) +gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table) { int i; Gene friend; @@ -340,7 +341,7 @@ gimme_gene(Edge edge, Edge *edge_table) /* random decision of the possible candidates to use */ - rand_decision = (int) geqo_randint(minimum_count - 1, 0); + rand_decision = geqo_randint(root, minimum_count - 1, 0); for (i = 0; i < edge.unused_edges; i++) @@ -368,7 +369,7 @@ gimme_gene(Edge edge, Edge *edge_table) * */ static Gene -edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene) +edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene) { int i; Gene fail_gene = gene[index]; @@ -401,7 +402,7 @@ edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene) if (four_count != 0) { - rand_decision = (int) geqo_randint(four_count - 1, 0); + rand_decision = geqo_randint(root, four_count - 1, 0); for (i = 1; i <= num_gene; i++) { @@ -423,7 +424,7 @@ edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene) else if (remaining_edges != 0) { /* random decision of the gene with remaining edges */ - rand_decision = (int) geqo_randint(remaining_edges - 1, 0); + rand_decision = geqo_randint(root, remaining_edges - 1, 0); for (i = 1; i <= num_gene; i++) { diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c index 04b3bfe72d..c20503b957 100644 --- a/src/backend/optimizer/geqo/geqo_eval.c +++ b/src/backend/optimizer/geqo/geqo_eval.c @@ -42,7 +42,7 @@ static bool desirable_join(PlannerInfo *root, * Returns cost of a query tree as an individual of the population. */ Cost -geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) +geqo_eval(PlannerInfo *root, Gene *tour, int num_gene) { MemoryContext mycontext; MemoryContext oldcxt; @@ -94,13 +94,13 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) * (If we are dealing with enough join rels, which we very likely are, a * new hash table will get built and used locally.) */ - savelength = list_length(evaldata->root->join_rel_list); - savehash = evaldata->root->join_rel_hash; + savelength = list_length(root->join_rel_list); + savehash = root->join_rel_hash; - evaldata->root->join_rel_hash = NULL; + root->join_rel_hash = NULL; /* construct the best path for the given combination of relations */ - joinrel = gimme_tree(tour, num_gene, evaldata); + joinrel = gimme_tree(root, tour, num_gene); /* * compute fitness @@ -117,9 +117,9 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) * Restore join_rel_list to its former state, and put back original * hashtable if any. */ - evaldata->root->join_rel_list = list_truncate(evaldata->root->join_rel_list, - savelength); - evaldata->root->join_rel_hash = savehash; + root->join_rel_list = list_truncate(root->join_rel_list, + savelength); + root->join_rel_hash = savehash; /* release all the memory acquired within gimme_tree */ MemoryContextSwitchTo(oldcxt); @@ -134,7 +134,6 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) * order. * * 'tour' is the proposed join order, of length 'num_gene' - * 'evaldata' contains the context we need * * Returns a new join relation whose cheapest path is the best plan for * this join order. NB: will return NULL if join order is invalid. @@ -153,8 +152,9 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) * plans. */ RelOptInfo * -gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) +gimme_tree(PlannerInfo *root, Gene *tour, int num_gene) { + GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; RelOptInfo **stack; int stack_depth; RelOptInfo *joinrel; @@ -193,7 +193,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) /* Get the next input relation and push it */ cur_rel_index = (int) tour[rel_count]; - stack[stack_depth] = (RelOptInfo *) list_nth(evaldata->initial_rels, + stack[stack_depth] = (RelOptInfo *) list_nth(private->initial_rels, cur_rel_index - 1); stack_depth++; @@ -211,7 +211,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) * have exhausted the input, the heuristics can't prevent popping. */ if (rel_count < num_gene - 1 && - !desirable_join(evaldata->root, outer_rel, inner_rel)) + !desirable_join(root, outer_rel, inner_rel)) break; /* @@ -220,7 +220,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) * root->join_rel_list yet, and so the paths constructed for it * will only include the ones we want. */ - joinrel = make_join_rel(evaldata->root, outer_rel, inner_rel); + joinrel = make_join_rel(root, outer_rel, inner_rel); /* Can't pop stack here if join order is not valid */ if (!joinrel) diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c index 72b0b5732e..2453678fc0 100644 --- a/src/backend/optimizer/geqo/geqo_main.c +++ b/src/backend/optimizer/geqo/geqo_main.c @@ -27,7 +27,9 @@ #include #include "optimizer/geqo_misc.h" +#include "optimizer/geqo_mutation.h" #include "optimizer/geqo_pool.h" +#include "optimizer/geqo_random.h" #include "optimizer/geqo_selection.h" @@ -38,6 +40,7 @@ int Geqo_effort; int Geqo_pool_size; int Geqo_generations; double Geqo_selection_bias; +double Geqo_seed; static int gimme_pool_size(int nr_rel); @@ -63,7 +66,7 @@ static int gimme_number_generations(int pool_size); RelOptInfo * geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) { - GeqoEvalData evaldata; + GeqoPrivateData private; int generation; Chromosome *momma; Chromosome *daddy; @@ -88,9 +91,12 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) int mutations = 0; #endif -/* set up evaldata */ - evaldata.root = root; - evaldata.initial_rels = initial_rels; +/* set up private information */ + root->join_search_private = (void *) &private; + private.initial_rels = initial_rels; + +/* initialize private number generator */ + geqo_set_seed(root, Geqo_seed); /* set GA parameters */ pool_size = gimme_pool_size(number_of_rels); @@ -98,13 +104,13 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) status_interval = 10; /* allocate genetic pool memory */ - pool = alloc_pool(pool_size, number_of_rels); + pool = alloc_pool(root, pool_size, number_of_rels); /* random initialization of the pool */ - random_init_pool(pool, &evaldata); + random_init_pool(root, pool); /* sort the pool according to cheapest path as fitness */ - sort_pool(pool); /* we have to do it only one time, since all + sort_pool(root, pool); /* we have to do it only one time, since all * kids replace the worst individuals in * future (-> geqo_pool.c:spread_chromo ) */ @@ -116,49 +122,49 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) #endif /* allocate chromosome momma and daddy memory */ - momma = alloc_chromo(pool->string_length); - daddy = alloc_chromo(pool->string_length); + momma = alloc_chromo(root, pool->string_length); + daddy = alloc_chromo(root, pool->string_length); #if defined (ERX) #ifdef GEQO_DEBUG elog(DEBUG2, "using edge recombination crossover [ERX]"); #endif /* allocate edge table memory */ - edge_table = alloc_edge_table(pool->string_length); + edge_table = alloc_edge_table(root, pool->string_length); #elif defined(PMX) #ifdef GEQO_DEBUG elog(DEBUG2, "using partially matched crossover [PMX]"); #endif /* allocate chromosome kid memory */ - kid = alloc_chromo(pool->string_length); + kid = alloc_chromo(root, pool->string_length); #elif defined(CX) #ifdef GEQO_DEBUG elog(DEBUG2, "using cycle crossover [CX]"); #endif /* allocate city table memory */ - kid = alloc_chromo(pool->string_length); - city_table = alloc_city_table(pool->string_length); + kid = alloc_chromo(root, pool->string_length); + city_table = alloc_city_table(root, pool->string_length); #elif defined(PX) #ifdef GEQO_DEBUG elog(DEBUG2, "using position crossover [PX]"); #endif /* allocate city table memory */ - kid = alloc_chromo(pool->string_length); - city_table = alloc_city_table(pool->string_length); + kid = alloc_chromo(root, pool->string_length); + city_table = alloc_city_table(root, pool->string_length); #elif defined(OX1) #ifdef GEQO_DEBUG elog(DEBUG2, "using order crossover [OX1]"); #endif /* allocate city table memory */ - kid = alloc_chromo(pool->string_length); - city_table = alloc_city_table(pool->string_length); + kid = alloc_chromo(root, pool->string_length); + city_table = alloc_city_table(root, pool->string_length); #elif defined(OX2) #ifdef GEQO_DEBUG elog(DEBUG2, "using order crossover [OX2]"); #endif /* allocate city table memory */ - kid = alloc_chromo(pool->string_length); - city_table = alloc_city_table(pool->string_length); + kid = alloc_chromo(root, pool->string_length); + city_table = alloc_city_table(root, pool->string_length); #endif @@ -168,45 +174,45 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) for (generation = 0; generation < number_generations; generation++) { /* SELECTION: using linear bias function */ - geqo_selection(momma, daddy, pool, Geqo_selection_bias); + geqo_selection(root, momma, daddy, pool, Geqo_selection_bias); #if defined (ERX) /* EDGE RECOMBINATION CROSSOVER */ - difference = gimme_edge_table(momma->string, daddy->string, pool->string_length, edge_table); + difference = gimme_edge_table(root, momma->string, daddy->string, pool->string_length, edge_table); kid = momma; /* are there any edge failures ? */ - edge_failures += gimme_tour(edge_table, kid->string, pool->string_length); + edge_failures += gimme_tour(root, edge_table, kid->string, pool->string_length); #elif defined(PMX) /* PARTIALLY MATCHED CROSSOVER */ - pmx(momma->string, daddy->string, kid->string, pool->string_length); + pmx(root, momma->string, daddy->string, kid->string, pool->string_length); #elif defined(CX) /* CYCLE CROSSOVER */ - cycle_diffs = cx(momma->string, daddy->string, kid->string, pool->string_length, city_table); + cycle_diffs = cx(root, momma->string, daddy->string, kid->string, pool->string_length, city_table); /* mutate the child */ if (cycle_diffs == 0) { mutations++; - geqo_mutation(kid->string, pool->string_length); + geqo_mutation(root, kid->string, pool->string_length); } #elif defined(PX) /* POSITION CROSSOVER */ - px(momma->string, daddy->string, kid->string, pool->string_length, city_table); + px(root, momma->string, daddy->string, kid->string, pool->string_length, city_table); #elif defined(OX1) /* ORDER CROSSOVER */ - ox1(momma->string, daddy->string, kid->string, pool->string_length, city_table); + ox1(root, momma->string, daddy->string, kid->string, pool->string_length, city_table); #elif defined(OX2) /* ORDER CROSSOVER */ - ox2(momma->string, daddy->string, kid->string, pool->string_length, city_table); + ox2(root, momma->string, daddy->string, kid->string, pool->string_length, city_table); #endif /* EVALUATE FITNESS */ - kid->worth = geqo_eval(kid->string, pool->string_length, &evaldata); + kid->worth = geqo_eval(root, kid->string, pool->string_length); /* push the kid into the wilderness of life according to its worth */ - spread_chromo(kid, pool); + spread_chromo(root, kid, pool); #ifdef GEQO_DEBUG @@ -249,7 +255,7 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) */ best_tour = (Gene *) pool->data[0].string; - best_rel = gimme_tree(best_tour, pool->string_length, &evaldata); + best_rel = gimme_tree(root, best_tour, pool->string_length); if (best_rel == NULL) elog(ERROR, "failed to make a valid plan"); @@ -260,28 +266,31 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) #endif /* ... free memory stuff */ - free_chromo(momma); - free_chromo(daddy); + free_chromo(root, momma); + free_chromo(root, daddy); #if defined (ERX) - free_edge_table(edge_table); + free_edge_table(root, edge_table); #elif defined(PMX) - free_chromo(kid); + free_chromo(root, kid); #elif defined(CX) - free_chromo(kid); - free_city_table(city_table); + free_chromo(root, kid); + free_city_table(root, city_table); #elif defined(PX) - free_chromo(kid); - free_city_table(city_table); + free_chromo(root, kid); + free_city_table(root, city_table); #elif defined(OX1) - free_chromo(kid); - free_city_table(city_table); + free_chromo(root, kid); + free_city_table(root, city_table); #elif defined(OX2) - free_chromo(kid); - free_city_table(city_table); + free_chromo(root, kid); + free_city_table(root, city_table); #endif - free_pool(pool); + free_pool(root, pool); + + /* ... clear root pointer to our private storage */ + root->join_search_private = NULL; return best_rel; } diff --git a/src/backend/optimizer/geqo/geqo_mutation.c b/src/backend/optimizer/geqo/geqo_mutation.c index 899410c42b..acf3b34534 100644 --- a/src/backend/optimizer/geqo/geqo_mutation.c +++ b/src/backend/optimizer/geqo/geqo_mutation.c @@ -36,21 +36,21 @@ #include "optimizer/geqo_random.h" void -geqo_mutation(Gene *tour, int num_gene) +geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene) { int swap1; int swap2; - int num_swaps = geqo_randint(num_gene / 3, 0); + int num_swaps = geqo_randint(root, num_gene / 3, 0); Gene temp; while (num_swaps > 0) { - swap1 = geqo_randint(num_gene - 1, 0); - swap2 = geqo_randint(num_gene - 1, 0); + swap1 = geqo_randint(root, num_gene - 1, 0); + swap2 = geqo_randint(root, num_gene - 1, 0); while (swap1 == swap2) - swap2 = geqo_randint(num_gene - 1, 0); + swap2 = geqo_randint(root, num_gene - 1, 0); temp = tour[swap1]; tour[swap1] = tour[swap2]; diff --git a/src/backend/optimizer/geqo/geqo_ox1.c b/src/backend/optimizer/geqo/geqo_ox1.c index cd979dfa4b..3419103d2a 100644 --- a/src/backend/optimizer/geqo/geqo_ox1.c +++ b/src/backend/optimizer/geqo/geqo_ox1.c @@ -43,7 +43,8 @@ * position crossover */ void -ox1(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +ox1(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, + City *city_table) { int left, right, @@ -56,8 +57,8 @@ ox1(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) city_table[k].used = 0; /* select portion to copy from tour1 */ - left = geqo_randint(num_gene - 1, 0); - right = geqo_randint(num_gene - 1, 0); + left = geqo_randint(root, num_gene - 1, 0); + right = geqo_randint(root, num_gene - 1, 0); if (left > right) { diff --git a/src/backend/optimizer/geqo/geqo_ox2.c b/src/backend/optimizer/geqo/geqo_ox2.c index 0d2e0def32..2526a35ef6 100644 --- a/src/backend/optimizer/geqo/geqo_ox2.c +++ b/src/backend/optimizer/geqo/geqo_ox2.c @@ -43,7 +43,7 @@ * position crossover */ void -ox2(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +ox2(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) { int k, j, @@ -60,12 +60,12 @@ ox2(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) } /* determine the number of positions to be inherited from tour1 */ - num_positions = geqo_randint(2 * num_gene / 3, num_gene / 3); + num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3); /* make a list of selected cities */ for (k = 0; k < num_positions; k++) { - pos = geqo_randint(num_gene - 1, 0); + pos = geqo_randint(root, num_gene - 1, 0); city_table[pos].select_list = (int) tour1[pos]; city_table[(int) tour1[pos]].used = 1; /* mark used */ } diff --git a/src/backend/optimizer/geqo/geqo_pmx.c b/src/backend/optimizer/geqo/geqo_pmx.c index fe9d4b4fc4..5a9a570664 100644 --- a/src/backend/optimizer/geqo/geqo_pmx.c +++ b/src/backend/optimizer/geqo/geqo_pmx.c @@ -43,7 +43,7 @@ * partially matched crossover */ void -pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene) +pmx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene) { int *failed = (int *) palloc((num_gene + 1) * sizeof(int)); int *from = (int *) palloc((num_gene + 1) * sizeof(int)); @@ -71,8 +71,8 @@ pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene) } /* locate crossover points */ - left = geqo_randint(num_gene - 1, 0); - right = geqo_randint(num_gene - 1, 0); + left = geqo_randint(root, num_gene - 1, 0); + right = geqo_randint(root, num_gene - 1, 0); if (left > right) { diff --git a/src/backend/optimizer/geqo/geqo_pool.c b/src/backend/optimizer/geqo/geqo_pool.c index 72eb34f3f3..64e23ba7c1 100644 --- a/src/backend/optimizer/geqo/geqo_pool.c +++ b/src/backend/optimizer/geqo/geqo_pool.c @@ -39,7 +39,7 @@ static int compare(const void *arg1, const void *arg2); * allocates memory for GA pool */ Pool * -alloc_pool(int pool_size, int string_length) +alloc_pool(PlannerInfo *root, int pool_size, int string_length) { Pool *new_pool; Chromosome *chromo; @@ -66,7 +66,7 @@ alloc_pool(int pool_size, int string_length) * deallocates memory for GA pool */ void -free_pool(Pool *pool) +free_pool(PlannerInfo *root, Pool *pool) { Chromosome *chromo; int i; @@ -88,7 +88,7 @@ free_pool(Pool *pool) * initialize genetic pool */ void -random_init_pool(Pool *pool, GeqoEvalData *evaldata) +random_init_pool(PlannerInfo *root, Pool *pool) { Chromosome *chromo = (Chromosome *) pool->data; int i; @@ -105,10 +105,9 @@ random_init_pool(Pool *pool, GeqoEvalData *evaldata) i = 0; while (i < pool->size) { - init_tour(chromo[i].string, pool->string_length); - pool->data[i].worth = geqo_eval(chromo[i].string, - pool->string_length, - evaldata); + init_tour(root, chromo[i].string, pool->string_length); + pool->data[i].worth = geqo_eval(root, chromo[i].string, + pool->string_length); if (pool->data[i].worth < DBL_MAX) i++; else @@ -133,7 +132,7 @@ random_init_pool(Pool *pool, GeqoEvalData *evaldata) * maybe you have to change compare() for different ordering ... */ void -sort_pool(Pool *pool) +sort_pool(PlannerInfo *root, Pool *pool) { qsort(pool->data, pool->size, sizeof(Chromosome), compare); } @@ -160,7 +159,7 @@ compare(const void *arg1, const void *arg2) * allocates a chromosome and string space */ Chromosome * -alloc_chromo(int string_length) +alloc_chromo(PlannerInfo *root, int string_length) { Chromosome *chromo; @@ -174,7 +173,7 @@ alloc_chromo(int string_length) * deallocates a chromosome and string space */ void -free_chromo(Chromosome *chromo) +free_chromo(PlannerInfo *root, Chromosome *chromo) { pfree(chromo->string); pfree(chromo); @@ -185,7 +184,7 @@ free_chromo(Chromosome *chromo) * assumes best->worst = smallest->largest */ void -spread_chromo(Chromosome *chromo, Pool *pool) +spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool) { int top, mid, @@ -247,7 +246,7 @@ spread_chromo(Chromosome *chromo, Pool *pool) * copy new gene into pool storage; always replace worst gene in pool */ - geqo_copy(&pool->data[pool->size - 1], chromo, pool->string_length); + geqo_copy(root, &pool->data[pool->size - 1], chromo, pool->string_length); swap_chromo.string = pool->data[pool->size - 1].string; swap_chromo.worth = pool->data[pool->size - 1].worth; diff --git a/src/backend/optimizer/geqo/geqo_px.c b/src/backend/optimizer/geqo/geqo_px.c index 07f41cd3f4..958e1bcc8e 100644 --- a/src/backend/optimizer/geqo/geqo_px.c +++ b/src/backend/optimizer/geqo/geqo_px.c @@ -43,7 +43,8 @@ * position crossover */ void -px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, + City *city_table) { int num_positions; @@ -57,12 +58,12 @@ px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) city_table[i].used = 0; /* choose random positions that will be inherited directly from parent */ - num_positions = geqo_randint(2 * num_gene / 3, num_gene / 3); + num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3); /* choose random position */ for (i = 0; i < num_positions; i++) { - pos = geqo_randint(num_gene - 1, 0); + pos = geqo_randint(root, num_gene - 1, 0); offspring[pos] = tour1[pos]; /* transfer cities to child */ city_table[(int) tour1[pos]].used = 1; /* mark city used */ diff --git a/src/backend/optimizer/geqo/geqo_random.c b/src/backend/optimizer/geqo/geqo_random.c new file mode 100644 index 0000000000..5a15c0c1a8 --- /dev/null +++ b/src/backend/optimizer/geqo/geqo_random.c @@ -0,0 +1,40 @@ +/*------------------------------------------------------------------------ + * + * geqo_random.c + * random number generator + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "optimizer/geqo_random.h" + + +void +geqo_set_seed(PlannerInfo *root, double seed) +{ + GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; + + /* + * XXX. This seeding algorithm could certainly be improved - but + * it is not critical to do so. + */ + memset(private->random_state, 0, sizeof(private->random_state)); + memcpy(private->random_state, + &seed, + Min(sizeof(private->random_state), sizeof(seed))); +} + +double +geqo_rand(PlannerInfo *root) +{ + GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; + + return erand48(private->random_state); +} diff --git a/src/backend/optimizer/geqo/geqo_recombination.c b/src/backend/optimizer/geqo/geqo_recombination.c index 3972fb1412..c36f3ac643 100644 --- a/src/backend/optimizer/geqo/geqo_recombination.c +++ b/src/backend/optimizer/geqo/geqo_recombination.c @@ -35,7 +35,7 @@ * and the procedure repeated. */ void -init_tour(Gene *tour, int num_gene) +init_tour(PlannerInfo *root, Gene *tour, int num_gene) { Gene *tmp; int remainder; @@ -53,7 +53,7 @@ init_tour(Gene *tour, int num_gene) for (i = 0; i < num_gene; i++) { /* choose value between 0 and remainder inclusive */ - next = (int) geqo_randint(remainder, 0); + next = geqo_randint(root, remainder, 0); /* output that element of the tmp array */ tour[i] = tmp[next]; /* and delete it */ @@ -81,7 +81,7 @@ init_tour(Gene *tour, int num_gene) * allocate memory for city table */ City * -alloc_city_table(int num_gene) +alloc_city_table(PlannerInfo *root, int num_gene) { City *city_table; @@ -99,7 +99,7 @@ alloc_city_table(int num_gene) * deallocate memory of city table */ void -free_city_table(City *city_table) +free_city_table(PlannerInfo *root, City *city_table) { pfree(city_table); } diff --git a/src/backend/optimizer/geqo/geqo_selection.c b/src/backend/optimizer/geqo/geqo_selection.c index d4f2c4d5dd..8a7e7dcda7 100644 --- a/src/backend/optimizer/geqo/geqo_selection.c +++ b/src/backend/optimizer/geqo/geqo_selection.c @@ -42,7 +42,7 @@ #include "optimizer/geqo_random.h" #include "optimizer/geqo_selection.h" -static int linear(int max, double bias); +static int linear(PlannerInfo *root, int max, double bias); /* @@ -51,22 +51,23 @@ static int linear(int max, double bias); * first and second genes are selected from the pool */ void -geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias) +geqo_selection(PlannerInfo *root, Chromosome *momma, Chromosome *daddy, + Pool *pool, double bias) { int first, second; - first = linear(pool->size, bias); - second = linear(pool->size, bias); + first = linear(root, pool->size, bias); + second = linear(root, pool->size, bias); if (pool->size > 1) { while (first == second) - second = linear(pool->size, bias); + second = linear(root, pool->size, bias); } - geqo_copy(momma, &pool->data[first], pool->string_length); - geqo_copy(daddy, &pool->data[second], pool->string_length); + geqo_copy(root, momma, &pool->data[first], pool->string_length); + geqo_copy(root, daddy, &pool->data[second], pool->string_length); } /* @@ -74,12 +75,13 @@ geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias) * generates random integer between 0 and input max number * using input linear bias * + * bias is y-intercept of linear distribution + * * probability distribution function is: f(x) = bias - 2(bias - 1)x * bias = (prob of first rule) / (prob of middle rule) */ static int -linear(int pool_size, double bias) /* bias is y-intercept of linear - * distribution */ +linear(PlannerInfo *root, int pool_size, double bias) { double index; /* index between 0 and pop_size */ double max = (double) pool_size; @@ -95,7 +97,7 @@ linear(int pool_size, double bias) /* bias is y-intercept of linear { double sqrtval; - sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand(); + sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand(root); if (sqrtval > 0.0) sqrtval = sqrt(sqrtval); index = max * (bias - sqrtval) / 2.0 / (bias - 1.0); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index bd02ddbe6d..8b1c40fcc0 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -2026,6 +2026,14 @@ static struct config_real ConfigureNamesReal[] = DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS, MAX_GEQO_SELECTION_BIAS, NULL, NULL }, + { + {"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO, + gettext_noop("GEQO: seed for random path selection."), + NULL + }, + &Geqo_seed, + 0.0, 0.0, 1.0, NULL, NULL + }, { {"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES, diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index c1b888c0d4..e50d7a44f7 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -213,6 +213,7 @@ #geqo_pool_size = 0 # selects default based on effort #geqo_generations = 0 # selects default based on effort #geqo_selection_bias = 2.0 # range 1.5-2.0 +#geqo_seed = 0.0 # range 0.0-1.0 # - Other Planner Options - diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index ea48889403..bbce826e0f 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -192,6 +192,9 @@ typedef struct PlannerInfo /* These fields are used only when hasRecursion is true: */ int wt_param_id; /* PARAM_EXEC ID for the work table */ struct Plan *non_recursive_plan; /* plan for non-recursive term */ + + /* optional private data for join_search_hook, e.g., GEQO */ + void *join_search_private; } PlannerInfo; diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h index ea4c812aae..d885a68e56 100644 --- a/src/include/optimizer/geqo.h +++ b/src/include/optimizer/geqo.h @@ -46,7 +46,7 @@ /* * Configuration options * - * If you change these, update backend/utils/misc/postgresql.sample.conf + * If you change these, update backend/utils/misc/postgresql.conf.sample */ extern int Geqo_effort; /* 1 .. 10, knob for adjustment of defaults */ @@ -64,16 +64,17 @@ extern double Geqo_selection_bias; #define MIN_GEQO_SELECTION_BIAS 1.5 #define MAX_GEQO_SELECTION_BIAS 2.0 +extern double Geqo_seed; /* 0 .. 1 */ + /* - * Data structure to encapsulate information needed for building plan trees - * (i.e., geqo_eval and gimme_tree). + * Private state for a GEQO run --- accessible via root->join_search_private */ typedef struct { - PlannerInfo *root; /* the query we are planning */ - List *initial_rels; /* the base relations */ -} GeqoEvalData; + List *initial_rels; /* the base relations we are joining */ + unsigned short random_state[3]; /* state for erand48() */ +} GeqoPrivateData; /* routines in geqo_main.c */ @@ -81,8 +82,7 @@ extern RelOptInfo *geqo(PlannerInfo *root, int number_of_rels, List *initial_rels); /* routines in geqo_eval.c */ -extern Cost geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata); -extern RelOptInfo *gimme_tree(Gene *tour, int num_gene, - GeqoEvalData *evaldata); +extern Cost geqo_eval(PlannerInfo *root, Gene *tour, int num_gene); +extern RelOptInfo *gimme_tree(PlannerInfo *root, Gene *tour, int num_gene); #endif /* GEQO_H */ diff --git a/src/include/optimizer/geqo_copy.h b/src/include/optimizer/geqo_copy.h index ae13059751..d96b969311 100644 --- a/src/include/optimizer/geqo_copy.h +++ b/src/include/optimizer/geqo_copy.h @@ -22,8 +22,9 @@ #ifndef GEQO_COPY_H #define GEQO_COPY_H -#include "optimizer/geqo_gene.h" +#include "optimizer/geqo.h" -extern void geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length); + +extern void geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2, int string_length); #endif /* GEQO_COPY_H */ diff --git a/src/include/optimizer/geqo_mutation.h b/src/include/optimizer/geqo_mutation.h index 0384de8b6f..c12ee4777d 100644 --- a/src/include/optimizer/geqo_mutation.h +++ b/src/include/optimizer/geqo_mutation.h @@ -22,8 +22,9 @@ #ifndef GEQO_MUTATION_H #define GEQO_MUTATION_H -#include "optimizer/geqo_gene.h" +#include "optimizer/geqo.h" -extern void geqo_mutation(Gene *tour, int num_gene); + +extern void geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene); #endif /* GEQO_MUTATION_H */ diff --git a/src/include/optimizer/geqo_pool.h b/src/include/optimizer/geqo_pool.h index 950e667d61..dbc6a01831 100644 --- a/src/include/optimizer/geqo_pool.h +++ b/src/include/optimizer/geqo_pool.h @@ -26,15 +26,15 @@ #include "optimizer/geqo.h" -extern Pool *alloc_pool(int pool_size, int string_length); -extern void free_pool(Pool *pool); +extern Pool *alloc_pool(PlannerInfo *root, int pool_size, int string_length); +extern void free_pool(PlannerInfo *root, Pool *pool); -extern void random_init_pool(Pool *pool, GeqoEvalData *evaldata); -extern Chromosome *alloc_chromo(int string_length); -extern void free_chromo(Chromosome *chromo); +extern void random_init_pool(PlannerInfo *root, Pool *pool); +extern Chromosome *alloc_chromo(PlannerInfo *root, int string_length); +extern void free_chromo(PlannerInfo *root, Chromosome *chromo); -extern void spread_chromo(Chromosome *chromo, Pool *pool); +extern void spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool); -extern void sort_pool(Pool *pool); +extern void sort_pool(PlannerInfo *root, Pool *pool); #endif /* GEQO_POOL_H */ diff --git a/src/include/optimizer/geqo_random.h b/src/include/optimizer/geqo_random.h index fab072828f..f24df44b18 100644 --- a/src/include/optimizer/geqo_random.h +++ b/src/include/optimizer/geqo_random.h @@ -26,13 +26,16 @@ #include -/* geqo_rand returns a random float value between 0 and 1 inclusive */ +#include "optimizer/geqo.h" -#define geqo_rand() ((double) random() / (double) MAX_RANDOM_VALUE) -/* geqo_randint returns integer value between lower and upper inclusive */ +extern void geqo_set_seed(PlannerInfo *root, double seed); -#define geqo_randint(upper,lower) \ - ( (int) floor( geqo_rand()*(((upper)-(lower))+0.999999) ) + (lower) ) +/* geqo_rand returns a random float value between 0 and 1 inclusive */ +extern double geqo_rand(PlannerInfo *root); + +/* geqo_randint returns integer value between lower and upper inclusive */ +#define geqo_randint(root, upper, lower) \ + ( (int) floor( geqo_rand(root)*(((upper)-(lower))+0.999999) ) + (lower) ) #endif /* GEQO_RANDOM_H */ diff --git a/src/include/optimizer/geqo_recombination.h b/src/include/optimizer/geqo_recombination.h index 2c4a338ca4..8feca11053 100644 --- a/src/include/optimizer/geqo_recombination.h +++ b/src/include/optimizer/geqo_recombination.h @@ -24,9 +24,10 @@ #ifndef GEQO_RECOMBINATION_H #define GEQO_RECOMBINATION_H -#include "optimizer/geqo_gene.h" +#include "optimizer/geqo.h" -extern void init_tour(Gene *tour, int num_gene); + +extern void init_tour(PlannerInfo *root, Gene *tour, int num_gene); /* edge recombination crossover [ERX] */ @@ -38,12 +39,14 @@ typedef struct Edge int unused_edges; } Edge; -extern Edge *alloc_edge_table(int num_gene); -extern void free_edge_table(Edge *edge_table); +extern Edge *alloc_edge_table(PlannerInfo *root, int num_gene); +extern void free_edge_table(PlannerInfo *root, Edge *edge_table); -extern float gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table); +extern float gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2, + int num_gene, Edge *edge_table); -extern int gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene); +extern int gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, + int num_gene); /* partially matched crossover [PMX] */ @@ -51,7 +54,9 @@ extern int gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene); #define DAD 1 /* indicator for gene from dad */ #define MOM 0 /* indicator for gene from mom */ -extern void pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene); +extern void pmx(PlannerInfo *root, + Gene *tour1, Gene *tour2, + Gene *offspring, int num_gene); typedef struct City @@ -62,19 +67,23 @@ typedef struct City int select_list; } City; -extern City *alloc_city_table(int num_gene); -extern void free_city_table(City *city_table); +extern City *alloc_city_table(PlannerInfo *root, int num_gene); +extern void free_city_table(PlannerInfo *root, City *city_table); /* cycle crossover [CX] */ -extern int cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table); +extern int cx(PlannerInfo *root, Gene *tour1, Gene *tour2, + Gene *offspring, int num_gene, City *city_table); /* position crossover [PX] */ -extern void px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table); +extern void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, + int num_gene, City *city_table); /* order crossover [OX1] according to Davis */ -extern void ox1(Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table); +extern void ox1(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring, + int num_gene, City *city_table); /* order crossover [OX2] according to Syswerda */ -extern void ox2(Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table); +extern void ox2(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring, + int num_gene, City *city_table); #endif /* GEQO_RECOMBINATION_H */ diff --git a/src/include/optimizer/geqo_selection.h b/src/include/optimizer/geqo_selection.h index 4b336d13ec..7177529fdd 100644 --- a/src/include/optimizer/geqo_selection.h +++ b/src/include/optimizer/geqo_selection.h @@ -23,8 +23,11 @@ #ifndef GEQO_SELECTION_H #define GEQO_SELECTION_H -#include "optimizer/geqo_gene.h" +#include "optimizer/geqo.h" -extern void geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias); + +extern void geqo_selection(PlannerInfo *root, + Chromosome *momma, Chromosome *daddy, + Pool *pool, double bias); #endif /* GEQO_SELECTION_H */ -- 2.30.2