进击的小白Day016——遗传算法(二)

这个遗传算法的程序没调通,瓶颈有两方面,一是对算法理解不够深刻,步骤不够熟悉,二是语言运用不熟练,表达不出想要的东西,看来现在来写这种及数量比较高的算法是不是还太早了。

贴代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.1415926
#define POP_SIZE 10
#define CHROM_LEN 5
#define EVO_MAX 10
#define BOUND_UP (0.9 * 3.1415926)
#define BOUND_DOWN 0
#define PCROSS 0.6
#define PVAR 0.1

/*目标函数*/
double func(double *p)
{
	double x1 = *p;
	double x2 = *(p + 1);
	double x3 = *(p + 2);
	double x4 = *(p + 3);
	double x5 = *(p + 4);
	double f = - 5 * sin(x1) * sin(x2) * sin(x3) * sin(x4) * sin(x5) 
			   - sin(5 * x1) * sin(5 * x2) * sin(5 * x3) * sin(5 * x4) * sin(5 * x5) + 8;
	return f;
}

/*初始化种群*/
void initPop(double p[POP_SIZE][CHROM_LEN])
{
	int i, j;
	for (i = 0; i < POP_SIZE; i++)
	{
		for (j = 0; j < CHROM_LEN; j++)
		{
			p[i][j] = BOUND_UP * (((double)rand()) / RAND_MAX);
		}
	}
}

/*求最小值*/
double *min_func(double p[POP_SIZE][CHROM_LEN])
{
	int i, j, index = 0;
	double min[2], min_f[POP_SIZE], _min;

	for (i = 0; i < POP_SIZE; i++)
	{
		min_f[i] = func(p[i]);
	}

	_min = min_f[0];
	for (i = 0; i < POP_SIZE; i++)
	{
		if (_min > min_f[i])
		{
			_min = min_f[i];
			index = i;
		}
	}

	min[0] = _min;
	min[1] = (double)index;

	return min;
}

/*选择操作*/
void choose(double p[POP_SIZE][CHROM_LEN])
{
	int index[POP_SIZE];
	double fitness[POP_SIZE], chooseP[POP_SIZE], accuP[POP_SIZE], p_temp[POP_SIZE][CHROM_LEN];
	double sum_fitness;
	double temp;
	int i, j;

	/*计算个体适应度*/
	for (i = 0, sum_fitness = 0; i < POP_SIZE; i++)
	{
		fitness[i] = 1 / func(p[i]);
		sum_fitness += fitness[i];
	}

	/*计算选择概率和累积概率*/
	for (i = 0; i < POP_SIZE; i++)
	{
		accuP[i] = 0;
	}
	for (i = 0; i < POP_SIZE; i++)
	{
		chooseP[i] = fitness[i] / sum_fitness;
		if (i == 0)
		{
			accuP[i] = chooseP[i];
		}
		else
		{
			accuP[i] = accuP[i - 1] + chooseP[i];
		}
		//printf("chooseP[%d]=%lf,accuP[%d]=%lf\n", i, chooseP[i], i, accuP[i]);
	}

	/*轮盘赌*/
	for (i = 0; i < POP_SIZE; i++)
	{
		do
		{
			temp = ((double)rand()) / RAND_MAX;
		} while (temp == 0);

		//printf("temp=%lf\n", temp);

		for (j = 0; j < POP_SIZE; j++)
		{
			if (temp < accuP[j])
			{
				index[i] = j;
				break;
			}
		}
	}
	/*for (i = 0; i < POP_SIZE; i++)
	{
		printf("index[%d]=%d\n", i, index[i]);
	}*/

	/*生成新种群*/
	for (i = 0; i < POP_SIZE; i++)
	{
		for (j = 0; j < CHROM_LEN; j++)
		{
			p_temp[i][j] = p[i][j];
		}
	}
	for (i = 0; i < POP_SIZE; i++)
	{
		for (j = 0; j < CHROM_LEN; j++)
		{
			p[i][j] = p_temp[index[i]][j];
		}
	}
}

/*交叉操作*/
void cross(double p[POP_SIZE][CHROM_LEN])
{
	int i, j, choice_1, choice_2, pos, flag;
	double p_1, p_2, b, p_cross;

	for (i = 0; i < POP_SIZE; i++)
	{
		p_cross = ((double)rand()) / RAND_MAX;
		if (p_cross > PCROSS)
		{
			continue;
		}

		/*随机选择2条染色体*/
		do
		{
			choice_1 = (int)(POP_SIZE * (((double)rand()) / RAND_MAX));
		} while (choice_1 > POP_SIZE - 1);
		do
		{
			choice_2 = (int)(POP_SIZE * (((double)rand()) / RAND_MAX));
		} while (choice_2 > POP_SIZE - 1);

		do
		{
			flag = 0;

			do
			{
				pos = (int)(CHROM_LEN * (((double)rand()) / RAND_MAX));
			} while (pos > CHROM_LEN - 1);

			p_1 = p[choice_1][pos];
			p_2 = p[choice_2][pos];

			b = ((double)rand()) / RAND_MAX;
			p[choice_1][pos] = p_1 * (1 - b) + p_2 * b;
			p[choice_2][pos] = p_2 * (1 - b) + p_1 * b;
			
			if (p[choice_1][pos] >= BOUND_DOWN && p[choice_1][pos] <= BOUND_UP && p[choice_2][pos] >= BOUND_DOWN && p[choice_2][pos] <= BOUND_UP)
			{
				flag = 1;
			}
		} while (flag == 0);
	}
}

void var(double p[POP_SIZE][CHROM_LEN])
{
	int i, choice, pos, flag;
	double p_var, f, r_1, r_2, pp;
	
	for (i = 0; i < POP_SIZE; i++)
	{
		p_var = ((double)rand()) / RAND_MAX;
		if (p_var > PVAR)
		{
			continue;
		}

		/*随机选择1条染色体*/
		do
		{
			choice = (int)(POP_SIZE * (((double)rand()) / RAND_MAX));
		} while (choice > POP_SIZE - 1);

		do
		{
			flag = 0;
			r_1 = ((double)rand()) / RAND_MAX;
			r_2 = ((double)rand()) / RAND_MAX;
			f = r_2 * (1 - ((double)i) / (double)EVO_MAX);

			do
			{
				pos = (int)(CHROM_LEN * (((double)rand()) / RAND_MAX));
			} while (pos > CHROM_LEN - 1);

			pp = p[choice][pos];

			if (r_1 >= 0.5)
			{
				p[choice][pos] = pp + (pp - (double)BOUND_UP) * f;
			}
			else
			{
				p[choice][pos] = pp + ((double)BOUND_DOWN - pp) * f;
			}

			if (p[choice][pos] >= BOUND_DOWN && p[choice][pos] <= BOUND_UP)
			{
				flag = 1;
			}
		} while (flag == 0);
	}
}

int main(void)
{
	int i, j;
	double pop[POP_SIZE][CHROM_LEN];
	double best_eve[EVO_MAX + 1], best_pos[EVO_MAX + 1], best, bestPos;
	double *best_zero;
	
	srand((double)time(NULL));

	/*初始化种群*/
	initPop(pop);
	best_zero = min_func(pop);
	best_eve[0] = *best_zero;
	best_pos[0] = *(best_zero + 1);
	printf("best_eve[0]=%lf\n", best_eve[0]);
	
	for (i = 1; i < (EVO_MAX + 1); i++)
	{
		choose(pop);
		cross(pop);
		var(pop);

		best_zero = min_func(pop);
		best_eve[i] = *best_zero;
		best_pos[i] = *(best_zero + 1);
		printf("best_eve[%d]=%lf\n",i , best_eve[0]);
	}

	best = best_eve[0];
	bestPos = best_pos[0];
	for (i = 0; i < (EVO_MAX + 1); i++)
	{
		if (best > best_eve[i])
		{
			best = best_eve[i];
			bestPos = best_pos[i];
		}
	}

	printf("best=%lf", best);
	
	return 0;
}

以下四种方式实现通过指针形参对数组元素值进行改变。

#include <stdio.h>

void One_A(int *a)
{
	int i;
	for (i = 0; i < 5; i++)
	{
		a[i] = i;
	}
}

void One_B(int b[])
{
	int i;
	for (i = 0; i < 5; i++)
	{
		b[i] = i;
	}
}

void Two_C(int c[][5])
{
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 5; j++)
		{
			c[i][j] = i + j;
		}
	}
}

void Two_D(int (*d)[5])
{
	int i, j;
	for (i = 0; i < 5; i++)
	{
		for (j = 0; j < 5; j++)
		{
			d[i][j] = i + j;
		}
	}
}

int main(void)
{
	int i;
	int a[5], b[5], c[5][5], d[5][5], e[5][5];
	One_A(a);
	One_B(b);
	Two_C(c);
	Two_D(d);
	printf("\n");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/u011232393/article/details/84314348
今日推荐