From 5e45211a64149b3c659b90ff2de6fa982a5a93ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 14:17:33 +0200 Subject: Adding upstream version 15.5. Signed-off-by: Daniel Baumann --- src/backend/optimizer/geqo/geqo_erx.c | 468 ++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 src/backend/optimizer/geqo/geqo_erx.c (limited to 'src/backend/optimizer/geqo/geqo_erx.c') diff --git a/src/backend/optimizer/geqo/geqo_erx.c b/src/backend/optimizer/geqo/geqo_erx.c new file mode 100644 index 0000000..cc06613 --- /dev/null +++ b/src/backend/optimizer/geqo/geqo_erx.c @@ -0,0 +1,468 @@ +/*------------------------------------------------------------------------ +* +* geqo_erx.c +* edge recombination crossover [ER] +* +* src/backend/optimizer/geqo/geqo_erx.c +* +*------------------------------------------------------------------------- +*/ + +/* contributed by: + =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= + * Martin Utesch * Institute of Automatic Control * + = = University of Mining and Technology = + * utesch@aut.tu-freiberg.de * Freiberg, Germany * + =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= + */ + +/* the edge recombination algorithm is adopted from Genitor : */ +/*************************************************************/ +/* */ +/* Copyright (c) 1990 */ +/* Darrell L. Whitley */ +/* Computer Science Department */ +/* Colorado State University */ +/* */ +/* Permission is hereby granted to copy all or any part of */ +/* this program for free distribution. The author's name */ +/* and this copyright notice must be included in any copy. */ +/* */ +/*************************************************************/ + + +#include "postgres.h" +#include "optimizer/geqo_random.h" +#include "optimizer/geqo_recombination.h" + +#if defined(ERX) + +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(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene); + + +/* alloc_edge_table + * + * allocate memory for edge table + * + */ + +Edge * +alloc_edge_table(PlannerInfo *root, int num_gene) +{ + Edge *edge_table; + + /* + * palloc one extra location so that nodes numbered 1..n can be indexed + * directly; 0 will not be used + */ + + edge_table = (Edge *) palloc((num_gene + 1) * sizeof(Edge)); + + return edge_table; +} + +/* free_edge_table + * + * deallocate memory of edge table + * + */ +void +free_edge_table(PlannerInfo *root, Edge *edge_table) +{ + pfree(edge_table); +} + +/* gimme_edge_table + * + * fills a data structure which represents the set of explicit + * edges between points in the (2) input genes + * + * assumes circular tours and bidirectional edges + * + * gimme_edge() will set "shared" edges to negative values + * + * returns average number edges/city in range 2.0 - 4.0 + * where 2.0=homogeneous; 4.0=diverse + * + */ +float +gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2, + int num_gene, Edge *edge_table) +{ + int i, + index1, + index2; + int edge_total; /* total number of unique edges in two genes */ + + /* at first clear the edge table's old data */ + for (i = 1; i <= num_gene; i++) + { + edge_table[i].total_edges = 0; + edge_table[i].unused_edges = 0; + } + + /* fill edge table with new data */ + + edge_total = 0; + + for (index1 = 0; index1 < num_gene; index1++) + { + /* + * presume the tour is circular, i.e. 1->2, 2->3, 3->1 this operation + * maps n back to 1 + */ + + index2 = (index1 + 1) % num_gene; + + /* + * edges are bidirectional, i.e. 1->2 is same as 2->1 call gimme_edge + * twice per edge + */ + + edge_total += gimme_edge(root, tour1[index1], tour1[index2], edge_table); + gimme_edge(root, tour1[index2], tour1[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 */ + return ((float) (edge_total * 2) / (float) num_gene); +} + +/* gimme_edge + * + * registers edge from city1 to city2 in input edge table + * + * no assumptions about directionality are made; + * therefore it is up to the calling routine to + * call gimme_edge twice to make a bi-directional edge + * between city1 and city2; + * uni-directional edges are possible as well (just call gimme_edge + * once with the direction from city1 to city2) + * + * returns 1 if edge was not already registered and was just added; + * 0 if edge was already registered and edge_table is unchanged + */ +static int +gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table) +{ + int i; + int edges; + int city1 = (int) gene1; + int city2 = (int) gene2; + + + /* check whether edge city1->city2 already exists */ + edges = edge_table[city1].total_edges; + + for (i = 0; i < edges; i++) + { + if ((Gene) Abs(edge_table[city1].edge_list[i]) == city2) + { + + /* mark shared edges as negative */ + edge_table[city1].edge_list[i] = 0 - city2; + + return 0; + } + } + + /* add city1->city2; */ + edge_table[city1].edge_list[edges] = city2; + + /* increment the number of edges from city1 */ + edge_table[city1].total_edges++; + edge_table[city1].unused_edges++; + + return 1; +} + +/* gimme_tour + * + * creates a new tour using edges from the edge table. + * priority is given to "shared" edges (i.e. edges which + * all parent genes possess and are marked as negative + * in the edge table.) + * + */ +int +gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, int num_gene) +{ + int i; + int edge_failures = 0; + + /* choose int between 1 and num_gene */ + new_gene[0] = (Gene) geqo_randint(root, num_gene, 1); + + for (i = 1; i < num_gene; i++) + { + /* + * as each point is entered into the tour, remove it from the 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(root, edge_table[(int) new_gene[i - 1]], edge_table); + + else + { /* cope with fault */ + edge_failures++; + + new_gene[i] = edge_failure(root, new_gene, i - 1, edge_table, num_gene); + } + + /* mark this node as incorporated */ + edge_table[(int) new_gene[i - 1]].unused_edges = -1; + } /* for (i=1; i= 0) + return (Gene) i; + + elog(LOG, "no edge found via looking for the last unused point"); + } + + + /* ... should never be reached */ + elog(ERROR, "no edge found"); + return 0; /* to keep the compiler quiet */ +} + +#endif /* defined(ERX) */ -- cgit v1.2.3