⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 geqo_erx.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------** geqo_erx.c*	 edge recombination crossover [ER]** $Id: geqo_erx.c,v 1.11.2.1 1999/08/02 05:57:04 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 "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 * */voidfree_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 * */floatgimme_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 intgimme_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; 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.) * */intgimme_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 < num_gene; i++)	{		/*		 * as each point is entered into the tour, remove it from the edge		 * table		 */		remove_gene(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);		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<num_gene; i++) */	return edge_failures;}/* remove_gene * *	 removes input gene from edge_table. *	 input edge is used *	 to identify deletion locations within edge table. * */static voidremove_gene(Gene gene, Edge edge, Edge *edge_table){	int			i,				j;	int			possess_edge;	int			genes_remaining;	/*	 * do for every gene known to have an edge to input gene (i.e. in	 * edge_list for input edge)	 */	for (i = 0; i < edge.unused_edges; i++)	{		possess_edge = (int) Abs(edge.edge_list[i]);		genes_remaining = edge_table[possess_edge].unused_edges;		/* find the input gene in all edge_lists and delete it */		for (j = 0; j < genes_remaining; j++)		{			if ((Gene) Abs(edge_table[possess_edge].edge_list[j]) == gene)			{				edge_table[possess_edge].unused_edges--;				edge_table[possess_edge].edge_list[j] =					edge_table[possess_edge].edge_list[genes_remaining - 1];				break;			}		}	}}/* gimme_gene * *	  priority is given to "shared" edges *	  (i.e. edges which both genes possess) * */static Genegimme_gene(Edge edge, Edge *edge_table){	int			i;	Gene		friend;	int			minimum_edges;	int			minimum_count = -1;	int			rand_decision;	/*	 * no point has edges to more than 4 other points thus, this contrived	 * minimum will be replaced	 */	minimum_edges = 5;	/* consider candidate destination points in edge list */	for (i = 0; i < edge.unused_edges; i++)	{		friend = (Gene) edge.edge_list[i];		/*		 * give priority to shared edges that are negative; so return 'em		 */		/*		 * negative values are caught here so we need not worry about		 * converting to absolute values		 */		if (friend < 0)			return (Gene) Abs(friend);		/*		 * give priority to candidates with fewest remaining unused edges;		 * find out what the minimum number of unused edges is		 * (minimum_edges); if there is more than one cadidate with the		 * minimum number of unused edges keep count of this number		 * (minimum_count);		 */		/*		 * The test for minimum_count can probably be removed at some		 * point but comments should probably indicate exactly why it is		 * guaranteed that the test will always succeed the first time		 * around.	If it can fail then the code is in error		 */		if (edge_table[(int) friend].unused_edges < minimum_edges)		{			minimum_edges = edge_table[(int) friend].unused_edges;			minimum_count = 1;		}		else if (minimum_count == -1)			elog(ERROR, "gimme_gene: Internal error - minimum_count not set");		else if (edge_table[(int) friend].unused_edges == minimum_edges)			minimum_count++;	}							/* for (i=0; i<edge.unused_edges; i++) */	/* random decision of the possible candidates to use */	rand_decision = (int) geqo_randint(minimum_count - 1, 0);	for (i = 0; i < edge.unused_edges; i++)	{		friend = (Gene) edge.edge_list[i];		/* return the chosen candidate point */		if (edge_table[(int) friend].unused_edges == minimum_edges)		{			minimum_count--;			if (minimum_count == rand_decision)				return friend;		}	}	/* ... should never be reached */	elog(ERROR, "gimme_gene: neither shared nor minimum number nor random edge found");	return 0;					/* to keep the compiler quiet */}/* edge_failure * *	  routine for handling edge failure * */static Geneedge_failure(Gene *gene, int index, Edge *edge_table, int num_gene){	int			i;	Gene		fail_gene = gene[index];	int			remaining_edges = 0;	int			four_count = 0;	int			rand_decision;	/*	 * how many edges remain? how many gene with four total (initial)	 * edges remain?	 */	for (i = 1; i <= num_gene; i++)	{		if ((edge_table[i].unused_edges != -1) && (i != (int) fail_gene))		{			remaining_edges++;			if (edge_table[i].total_edges == 4)				four_count++;		}	}	/*	 * random decision of the gene with remaining edges and whose	 * total_edges == 4	 */	if (four_count != 0)	{		rand_decision = (int) geqo_randint(four_count - 1, 0);		for (i = 1; i <= num_gene; i++)		{			if ((Gene) i != fail_gene &&				edge_table[i].unused_edges != -1 &&				edge_table[i].total_edges == 4)			{				four_count--;				if (rand_decision == four_count)					return (Gene) i;			}		}		elog(DEBUG, "edge_failure(1): no edge found via random decision and total_edges == 4");	}	else/* random decision of the gene with remaining edges */	if (remaining_edges != 0)	{		rand_decision = (int) geqo_randint(remaining_edges - 1, 0);		for (i = 1; i <= num_gene; i++)		{			if ((Gene) i != fail_gene &&				edge_table[i].unused_edges != -1)			{				remaining_edges--;				if (rand_decision == remaining_edges)					return i;			}		}		elog(DEBUG, "edge_failure(2): no edge found via random decision and remainig edges");	}	/*	 * edge table seems to be empty; this happens sometimes on the last	 * point due to the fact that the first point is removed from the	 * table even though only one of its edges has been determined	 */	else	{							/* occurs only at the last point in the								 * tour; simply look for the point which								 * is not yet used */		for (i = 1; i <= num_gene; i++)			if (edge_table[i].unused_edges >= 0)				return (Gene) i;		elog(DEBUG, "edge_failure(3): no edge found via looking for the last ununsed point");	}/* ... should never be reached */	elog(ERROR, "edge_failure: no edge detected");	return 0;					/* to keep the compiler quiet */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -