/*------------------------------------------------------------------------ * * geqo_erx.c-- * edge recombination crossover [ER] * * $Id: geqo_erx.c,v 1.2 1997/06/06 00:37:23 scrappy Exp $ * *------------------------------------------------------------------------- */ /* 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 "nodes/pg_list.h" #include "nodes/relation.h" #include "nodes/primnodes.h" #include "utils/palloc.h" #include "utils/elog.h" #include "optimizer/internal.h" #include "optimizer/paths.h" #include "optimizer/pathnode.h" #include "optimizer/clauses.h" #include "optimizer/cost.h" #include "optimizer/geqo_gene.h" #include "optimizer/geqo.h" #include "optimizer/geqo_recombination.h" #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 Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene); /* alloc_edge_table-- * * allocate memory for edge table * */ Edge * alloc_edge_table(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(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 (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 operaton 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(tour1[index1], tour1[index2], edge_table); gimme_edge(tour1[index2], tour1[index1], edge_table); edge_total += gimme_edge(tour2[index1], tour2[index2], edge_table); gimme_edge(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; * therefor 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 (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; icity2; */ 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 (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 */ for (i=1; i 0) { new_gene[i] = gimme_gene(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); } /* mark this node as incorporated */ edge_table[(int) new_gene[i-1]].unused_edges = -1; } /* for (i=1; i= 0) return ((Gene) i); elog(DEBUG,"edge_failure(3): no edge found via looking for the last ununsed point"); } /* ... should never be reached */ elog(WARN,"edge_failure: no edge detected"); return 0; /* to keep the compiler quiet */ }