geqo_erx.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:11k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*------------------------------------------------------------------------
  2. *
  3. * geqo_erx.c
  4. *  edge recombination crossover [ER]
  5. *
  6. * $Id: geqo_erx.c,v 1.11.2.1 1999/08/02 05:57:04 scrappy Exp $
  7. *
  8. *-------------------------------------------------------------------------
  9. */
  10. /* contributed by:
  11.    =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  12.    *  Martin Utesch  * Institute of Automatic Control    *
  13.    =  = University of Mining and Technology =
  14.    *  utesch@aut.tu-freiberg.de  * Freiberg, Germany    *
  15.    =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  16.  */
  17. /* the edge recombination algorithm is adopted from Genitor : */
  18. /*************************************************************/
  19. /*  */
  20. /* Copyright (c) 1990  */
  21. /* Darrell L. Whitley  */
  22. /* Computer Science Department  */
  23. /* Colorado State University  */
  24. /*  */
  25. /* Permission is hereby granted to copy all or any part of  */
  26. /* this program for free distribution.   The author's name  */
  27. /* and this copyright notice must be included in any copy.  */
  28. /*  */
  29. /*************************************************************/
  30. #include "postgres.h"
  31. #include "optimizer/geqo_recombination.h"
  32. #include "optimizer/geqo_random.h"
  33. static int gimme_edge(Gene gene1, Gene gene2, Edge *edge_table);
  34. static void remove_gene(Gene gene, Edge edge, Edge *edge_table);
  35. static Gene gimme_gene(Edge edge, Edge *edge_table);
  36. static Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene);
  37. /* alloc_edge_table
  38.  *
  39.  *  allocate memory for edge table
  40.  *
  41.  */
  42. Edge *
  43. alloc_edge_table(int num_gene)
  44. {
  45. Edge    *edge_table;
  46. /*
  47.  * palloc one extra location so that nodes numbered 1..n can be
  48.  * indexed directly; 0 will not be used
  49.  */
  50. edge_table = (Edge *) palloc((num_gene + 1) * sizeof(Edge));
  51. return edge_table;
  52. }
  53. /* free_edge_table
  54.  *
  55.  *   deallocate memory of edge table
  56.  *
  57.  */
  58. void
  59. free_edge_table(Edge *edge_table)
  60. {
  61. pfree(edge_table);
  62. }
  63. /* gimme_edge_table
  64.  *
  65.  *  fills a data structure which represents the set of explicit
  66.  *  edges between points in the (2) input genes
  67.  *
  68.  *  assumes circular tours and bidirectional edges
  69.  *
  70.  *  gimme_edge() will set "shared" edges to negative values
  71.  *
  72.  *  returns average number edges/city in range 2.0 - 4.0
  73.  *  where 2.0=homogeneous; 4.0=diverse
  74.  *
  75.  */
  76. float
  77. gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table)
  78. {
  79. int i,
  80. index1,
  81. index2;
  82. int edge_total; /* total number of unique edges in two
  83.  * genes */
  84. /* at first clear the edge table's old data */
  85. for (i = 1; i <= num_gene; i++)
  86. {
  87. edge_table[i].total_edges = 0;
  88. edge_table[i].unused_edges = 0;
  89. }
  90. /* fill edge table with new data */
  91. edge_total = 0;
  92. for (index1 = 0; index1 < num_gene; index1++)
  93. {
  94. /*
  95.  * presume the tour is circular, i.e. 1->2, 2->3, 3->1 this
  96.  * operaton maps n back to 1
  97.  */
  98. index2 = (index1 + 1) % num_gene;
  99. /*
  100.  * edges are bidirectional, i.e. 1->2 is same as 2->1 call
  101.  * gimme_edge twice per edge
  102.  */
  103. edge_total += gimme_edge(tour1[index1], tour1[index2], edge_table);
  104. gimme_edge(tour1[index2], tour1[index1], edge_table);
  105. edge_total += gimme_edge(tour2[index1], tour2[index2], edge_table);
  106. gimme_edge(tour2[index2], tour2[index1], edge_table);
  107. }
  108. /* return average number of edges per index */
  109. return ((float) (edge_total * 2) / (float) num_gene);
  110. }
  111. /* gimme_edge
  112.  *
  113.  *   registers edge from city1 to city2 in input edge table
  114.  *
  115.  *   no assumptions about directionality are made;
  116.  *   therefor it is up to the calling routine to
  117.  *   call gimme_edge twice to make a bi-directional edge
  118.  *   between city1 and city2;
  119.  *   uni-directional edges are possible as well (just call gimme_edge
  120.  *   once with the direction from city1 to city2)
  121.  *
  122.  *   returns 1 if edge was not already registered and was just added;
  123.  *   0 if edge was already registered and edge_table is unchanged
  124.  */
  125. static int
  126. gimme_edge(Gene gene1, Gene gene2, Edge *edge_table)
  127. {
  128. int i;
  129. int edges;
  130. int city1 = (int) gene1;
  131. int city2 = (int) gene2;
  132. /* check whether edge city1->city2 already exists */
  133. edges = edge_table[city1].total_edges;
  134. for (i = 0; i < edges; i++)
  135. {
  136. if ((Gene) Abs(edge_table[city1].edge_list[i]) == city2)
  137. {
  138. /* mark shared edges as negative */
  139. edge_table[city1].edge_list[i] = 0 - city2;
  140. return 0;
  141. }
  142. }
  143. /* add city1->city2; */
  144. edge_table[city1].edge_list[edges] = city2;
  145. /* increment the number of edges from city1 */
  146. edge_table[city1].total_edges++;
  147. edge_table[city1].unused_edges++;
  148. return 1;
  149. }
  150. /* gimme_tour
  151.  *
  152.  *   creates a new tour using edges from the edge table.
  153.  *   priority is given to "shared" edges (i.e. edges which
  154.  *   all parent genes possess and are marked as negative
  155.  *   in the edge table.)
  156.  *
  157.  */
  158. int
  159. gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene)
  160. {
  161. int i;
  162. int edge_failures = 0;
  163. new_gene[0] = (Gene) geqo_randint(num_gene, 1); /* choose int between 1
  164.  * and num_gene */
  165. for (i = 1; i < num_gene; i++)
  166. {
  167. /*
  168.  * as each point is entered into the tour, remove it from the edge
  169.  * table
  170.  */
  171. remove_gene(new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table);
  172. /* find destination for the newly entered point */
  173. if (edge_table[new_gene[i - 1]].unused_edges > 0)
  174. new_gene[i] = gimme_gene(edge_table[(int) new_gene[i - 1]], edge_table);
  175. else
  176. { /* cope with fault */
  177. edge_failures++;
  178. new_gene[i] = edge_failure(new_gene, i - 1, edge_table, num_gene);
  179. }
  180. /* mark this node as incorporated */
  181. edge_table[(int) new_gene[i - 1]].unused_edges = -1;
  182. } /* for (i=1; i<num_gene; i++) */
  183. return edge_failures;
  184. }
  185. /* remove_gene
  186.  *
  187.  *  removes input gene from edge_table.
  188.  *  input edge is used
  189.  *  to identify deletion locations within edge table.
  190.  *
  191.  */
  192. static void
  193. remove_gene(Gene gene, Edge edge, Edge *edge_table)
  194. {
  195. int i,
  196. j;
  197. int possess_edge;
  198. int genes_remaining;
  199. /*
  200.  * do for every gene known to have an edge to input gene (i.e. in
  201.  * edge_list for input edge)
  202.  */
  203. for (i = 0; i < edge.unused_edges; i++)
  204. {
  205. possess_edge = (int) Abs(edge.edge_list[i]);
  206. genes_remaining = edge_table[possess_edge].unused_edges;
  207. /* find the input gene in all edge_lists and delete it */
  208. for (j = 0; j < genes_remaining; j++)
  209. {
  210. if ((Gene) Abs(edge_table[possess_edge].edge_list[j]) == gene)
  211. {
  212. edge_table[possess_edge].unused_edges--;
  213. edge_table[possess_edge].edge_list[j] =
  214. edge_table[possess_edge].edge_list[genes_remaining - 1];
  215. break;
  216. }
  217. }
  218. }
  219. }
  220. /* gimme_gene
  221.  *
  222.  *   priority is given to "shared" edges
  223.  *   (i.e. edges which both genes possess)
  224.  *
  225.  */
  226. static Gene
  227. gimme_gene(Edge edge, Edge *edge_table)
  228. {
  229. int i;
  230. Gene friend;
  231. int minimum_edges;
  232. int minimum_count = -1;
  233. int rand_decision;
  234. /*
  235.  * no point has edges to more than 4 other points thus, this contrived
  236.  * minimum will be replaced
  237.  */
  238. minimum_edges = 5;
  239. /* consider candidate destination points in edge list */
  240. for (i = 0; i < edge.unused_edges; i++)
  241. {
  242. friend = (Gene) edge.edge_list[i];
  243. /*
  244.  * give priority to shared edges that are negative; so return 'em
  245.  */
  246. /*
  247.  * negative values are caught here so we need not worry about
  248.  * converting to absolute values
  249.  */
  250. if (friend < 0)
  251. return (Gene) Abs(friend);
  252. /*
  253.  * give priority to candidates with fewest remaining unused edges;
  254.  * find out what the minimum number of unused edges is
  255.  * (minimum_edges); if there is more than one cadidate with the
  256.  * minimum number of unused edges keep count of this number
  257.  * (minimum_count);
  258.  */
  259. /*
  260.  * The test for minimum_count can probably be removed at some
  261.  * point but comments should probably indicate exactly why it is
  262.  * guaranteed that the test will always succeed the first time
  263.  * around. If it can fail then the code is in error
  264.  */
  265. if (edge_table[(int) friend].unused_edges < minimum_edges)
  266. {
  267. minimum_edges = edge_table[(int) friend].unused_edges;
  268. minimum_count = 1;
  269. }
  270. else if (minimum_count == -1)
  271. elog(ERROR, "gimme_gene: Internal error - minimum_count not set");
  272. else if (edge_table[(int) friend].unused_edges == minimum_edges)
  273. minimum_count++;
  274. } /* for (i=0; i<edge.unused_edges; i++) */
  275. /* random decision of the possible candidates to use */
  276. rand_decision = (int) geqo_randint(minimum_count - 1, 0);
  277. for (i = 0; i < edge.unused_edges; i++)
  278. {
  279. friend = (Gene) edge.edge_list[i];
  280. /* return the chosen candidate point */
  281. if (edge_table[(int) friend].unused_edges == minimum_edges)
  282. {
  283. minimum_count--;
  284. if (minimum_count == rand_decision)
  285. return friend;
  286. }
  287. }
  288. /* ... should never be reached */
  289. elog(ERROR, "gimme_gene: neither shared nor minimum number nor random edge found");
  290. return 0; /* to keep the compiler quiet */
  291. }
  292. /* edge_failure
  293.  *
  294.  *   routine for handling edge failure
  295.  *
  296.  */
  297. static Gene
  298. edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene)
  299. {
  300. int i;
  301. Gene fail_gene = gene[index];
  302. int remaining_edges = 0;
  303. int four_count = 0;
  304. int rand_decision;
  305. /*
  306.  * how many edges remain? how many gene with four total (initial)
  307.  * edges remain?
  308.  */
  309. for (i = 1; i <= num_gene; i++)
  310. {
  311. if ((edge_table[i].unused_edges != -1) && (i != (int) fail_gene))
  312. {
  313. remaining_edges++;
  314. if (edge_table[i].total_edges == 4)
  315. four_count++;
  316. }
  317. }
  318. /*
  319.  * random decision of the gene with remaining edges and whose
  320.  * total_edges == 4
  321.  */
  322. if (four_count != 0)
  323. {
  324. rand_decision = (int) geqo_randint(four_count - 1, 0);
  325. for (i = 1; i <= num_gene; i++)
  326. {
  327. if ((Gene) i != fail_gene &&
  328. edge_table[i].unused_edges != -1 &&
  329. edge_table[i].total_edges == 4)
  330. {
  331. four_count--;
  332. if (rand_decision == four_count)
  333. return (Gene) i;
  334. }
  335. }
  336. elog(DEBUG, "edge_failure(1): no edge found via random decision and total_edges == 4");
  337. }
  338. else
  339. /* random decision of the gene with remaining edges */
  340. if (remaining_edges != 0)
  341. {
  342. rand_decision = (int) geqo_randint(remaining_edges - 1, 0);
  343. for (i = 1; i <= num_gene; i++)
  344. {
  345. if ((Gene) i != fail_gene &&
  346. edge_table[i].unused_edges != -1)
  347. {
  348. remaining_edges--;
  349. if (rand_decision == remaining_edges)
  350. return i;
  351. }
  352. }
  353. elog(DEBUG, "edge_failure(2): no edge found via random decision and remainig edges");
  354. }
  355. /*
  356.  * edge table seems to be empty; this happens sometimes on the last
  357.  * point due to the fact that the first point is removed from the
  358.  * table even though only one of its edges has been determined
  359.  */
  360. else
  361. { /* occurs only at the last point in the
  362.  * tour; simply look for the point which
  363.  * is not yet used */
  364. for (i = 1; i <= num_gene; i++)
  365. if (edge_table[i].unused_edges >= 0)
  366. return (Gene) i;
  367. elog(DEBUG, "edge_failure(3): no edge found via looking for the last ununsed point");
  368. }
  369. /* ... should never be reached */
  370. elog(ERROR, "edge_failure: no edge detected");
  371. return 0; /* to keep the compiler quiet */
  372. }