分享
 
 
 

遗传算法的一个例子(C/C++)

王朝c/c++·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

遗传算法的一个例子(C/C++)

作者:newsuppy

摘要: m个工件分配给m架机床的效益最优化问题,使用一种遗传算法解决。

一,已知效益矩阵E

eij

M1

M2

M3

M4

M5

J1

5

6

4

8

3

J2

6

4

9

8

5

J3

4

3

2

5

4

J4

7

2

4

5

3

J5

3

6

4

5

5

Jn为工件,Mn为机床,矩阵对应的一格即为,某工件分配给某机床的效益。效益指花费的时间,金钱等,数值越大越差。产生一个分配序列C=(5,2,3,4,1)指将5号工件分配给1号机床,2号工件分配给2号机床,以此类推求得当前分配对应的效益为3+4+2+5+3=17。最佳化问题就是要求该效益值最小时对应的分配序列。下面采用一种遗传算法,具体算法这里不再复述,可以参考[1]或其他相关书籍。要注意由于工件与机床是一一对应的,算法与一些常见的遗传算法在某些细节上有所不同,如染色体编码,到位,变异。

下面是算法实现,由于某些原因,不得不采用C/C++混合编码,C++代码主要在文件输入输出部分。另外要让程序正常运行需要包括几个支持文件(与程序在同一路径):

benefit.txt输入效益矩阵

num_of_gen.txt最后产生的代序

numofcolony.txt为群体中个体总数

numoftm.txt为工件数与机床数

内容可以如下:

benefit.txt

5 6 4 8 3

6 4 9 8 5

4 3 2 5 4

7 2 4 5 3

3 6 4 5 5

num_of_gen.txt

50

numofcolony.txt

10

numoftm.txt

5

5

注意:由于程序写得比较仓促,未考虑错误处理,请保证相关文件的正确性。

#include <iostream>

#include <fstream>

#include <algorithm>

#include <numeric>

#include <stdlib.h>

#include <time.h>

#include <math.h>

using namespace std;

void generate_colony(int **colony, int num_of_chromosomes, int num_of_job); //初始群体产生

int compute_benefit(int **benefit_matrix, int *chromosome, int num_of_machine); // 对单个染色体的效益评估

void copy_chromosomes(int **colony, int num_of_chromosomes, int num_of_job, int *benefit_array);//复制

int execute_probably(float probability); //按一定概率返回1或0

//上面的函数实现中使用rand产生随机数,这是不严格的,应该采用一个均匀(Uniform)分布的随机数生成器

void exchange_gene(int *chromosome_first, int *chromosome_second, int num_of_job); //对两个染色体实行交换

void reverse_gene(int *chromosome, int num_of_job); //对单个染色体实行到位

void gene_mutate(int *chromosome, int num_of_job); //对单个染色体实行变异

void ERV_colony(int **colony, float pe, float pr, float pv, int num_of_job, int num_of_chromosomes);

//对群体按概率实行交换,到位和变异

int main()

{

int **benefit_matrix = NULL; // 效益矩阵

int num_of_job; // 工件数

int num_of_machine; // 机床数

ifstream inputTM("numoftm.txt");

inputTM >> num_of_job >> num_of_machine;

inputTM.close();

benefit_matrix = (int**)malloc(sizeof(int*)*num_of_job);

for (int i=0; i<num_of_job; ++i)

{

benefit_matrix[i] = (int*)malloc(sizeof(int)*num_of_machine);

}

ifstream inputBenefit("benefit.txt");

for (int i=0; i<num_of_job; ++i)

{

for (int j=0; j<num_of_machine; ++j)

{

inputBenefit >> benefit_matrix[i][j];

}

}

inputBenefit.close();

/*********************************************

// Test for inital data's input

cout <<num_of_job << '\t' << num_of_machine << endl;

for (int i=0; i<num_of_job; ++i)

{

for (int j=0; j<num_of_machine; ++j)

{

cout << benefit_matrix[i][j] << '\t';

}

cout << '\n';

}

**********************************************/

int num_of_chromosomes; //群体数

ifstream inputCln("numofcolony.txt");

inputCln >> num_of_chromosomes;

inputCln.close();

int **colony = NULL; //群体

colony = (int**)malloc(sizeof(int*)*num_of_chromosomes);

for (int i=0; i<num_of_chromosomes; ++i)

{

colony[i] =(int*)malloc(sizeof(int)*num_of_job);

}

srand(time(0));

generate_colony(colony, num_of_chromosomes, num_of_job);

cout << "Origin Colonies" << '\n';

/***********************************/

// Test for genetare_colony

for (int i=0; i<num_of_chromosomes; ++i)

{

for (int j=0; j<num_of_job; ++j)

{

cout << colony[i][j] << '\t';

}

cout << '\n';

}

/************************************/

int *benefit_array = NULL; // 群体中每个个体的效益组成的数组

benefit_array = (int*)malloc(sizeof(int)*num_of_chromosomes);

for (int i=0; i<num_of_chromosomes; ++i)

{

benefit_array[i] = compute_benefit(benefit_matrix, colony[i], num_of_machine);

}

cout << "Current benefit" << '\n'

<< "mean:" << (float)accumulate(benefit_array, benefit_array+num_of_chromosomes, 0) / num_of_chromosomes << '\t'

<< "max:" << *max_element(benefit_array, benefit_array+num_of_chromosomes) << '\t'

<< "min:" << *min_element(benefit_array, benefit_array+num_of_chromosomes) << '\n';

int num_of_gen; // 产生的代数,也就是最后产生的那个代的序数

ifstream inputNG("num_of_gen.txt");

inputNG >> num_of_gen;

inputNG.close();

float probability_of_exchange = 0.7f;

float probability_of_reverse = 0.2f;

float probability_of_mutate = 0.01f;

for (int i=0; i<num_of_gen; ++i)

{

//调用复制子程序

copy_chromosomes(colony, num_of_chromosomes, num_of_job, benefit_array);

ERV_colony(colony, probability_of_exchange, probability_of_reverse, probability_of_mutate,

num_of_job, num_of_chromosomes);

//重新计算各个个体的效益

for (int j=0; j<num_of_chromosomes; ++j)

{

benefit_array[j] = compute_benefit(benefit_matrix, colony[j], num_of_machine);

}

//本代评估效益

cout << "current gen : " << i+1 << '\n'

<< "mean: " << (float)accumulate(benefit_array, benefit_array+num_of_chromosomes, 0) / num_of_chromosomes << '\t'

<< "max:" << *max_element(benefit_array, benefit_array+num_of_chromosomes) << '\t'

<< "min:" << *min_element(benefit_array, benefit_array+num_of_chromosomes) << '\n';

}

cout << "Laster Colony" << '\n';

for (int i=0; i<num_of_chromosomes; ++i)

{

for (int j=0; j<num_of_job; ++j)

{

cout << colony[i][j] << '\t';

}

cout << '\n';

}

// free all resource

for (int i=0; i<num_of_job; ++i)

{

free(benefit_matrix[i]);

}

free(benefit_matrix);

for (int i=0; i<num_of_chromosomes; ++i)

{

free(colony[i]);

}

free(colony);

free(benefit_array);

system("pause");

}

void generate_colony(int **colony, int num_of_chromosomes, int num_of_job)

{

int *initial_array = (int*)malloc(sizeof(int)*num_of_job);

for (int i=0; i<num_of_job; ++i)

{

initial_array[i] = i + 1;

}

for (int i=0; i<num_of_chromosomes; ++i)

{

random_shuffle(initial_array, initial_array+num_of_job);

copy(initial_array, initial_array+num_of_job, colony[i]);

}

free(initial_array);

}

int compute_benefit(int **benefit_matrix, int *chromosome, int num_of_machine)

{

int benefit = 0;

for (int i=0; i<num_of_machine; ++i)

{

benefit += benefit_matrix[chromosome[i]-1][i];

}

return benefit;

}

void copy_chromosomes(int **colony, int num_of_chromosomes, int num_of_job, int *benefit_array)

{

int i, j;

int *next_gen_reserve; //各个个体在后代中的复制量

int hasCopyed = 0; // 防止复制数超过群体总数??

int **temp_colony; //暂存群体

float mean, max_benefit, min_benefit;

float big_separator, small_separator;

mean = (float)accumulate(benefit_array, benefit_array+num_of_chromosomes, 0) / (float)num_of_chromosomes;

max_benefit = *max_element(benefit_array, benefit_array+num_of_chromosomes);

min_benefit = *min_element(benefit_array, benefit_array+num_of_chromosomes);

big_separator = max_benefit - (max_benefit-mean) / 2;

small_separator = min_benefit + (mean-min_benefit) / 2;

temp_colony = (int**)malloc(sizeof(int*)*num_of_chromosomes);

for (i=0; i<num_of_chromosomes; ++i)

{

temp_colony[i] =(int*)malloc(sizeof(int)*num_of_job);

}

// 复制暂存群体

for (i=0; i<num_of_chromosomes; ++i)

{

for (j=0; j<num_of_job; ++j)

{

temp_colony[i][j] = colony[i][j];

}

}

next_gen_reserve = (int*)malloc(sizeof(int)*num_of_chromosomes);

// 计算个体贡献并进行参数圆整

for (i=0; i<num_of_chromosomes; ++i)

{

if (benefit_array[i] >= big_separator)

next_gen_reserve[i] = 0;

else if (benefit_array[i] <= small_separator)

next_gen_reserve[i] = 2;

else

next_gen_reserve[i] = 1;

}

for (i=0; i<num_of_chromosomes; ++i)

{

for (j=0; j<next_gen_reserve[i]; ++j)

{

if (hasCopyed >= num_of_chromosomes)

{

i = num_of_chromosomes;

break;

}

memcpy(colony[hasCopyed], temp_colony[i], sizeof(colony[0][0])*num_of_job);

++hasCopyed;

}

}

for (i=0; i<num_of_chromosomes; ++i)

{

free(temp_colony[i]);

}

free(temp_colony);

free(next_gen_reserve);

}

int execute_probably(float probability)

{

if (probability > 1.0)

return 1;

else if (probability <= 0.0)

return 0;

else

{

int rndNum = rand() % 1000;

if (rndNum < (int)(probability * 1000.0))

return 1;

else

return 0;

}

}

void exchange_gene(int *chromosome_first, int *chromosome_second, int num_of_job)

{

int exchange_pos; //交换随机点

int *derived_first, *derived_second; //交换后的两个新子代的临时存放

int i, j, k;

int is_equal;

exchange_pos = rand() % num_of_job;

derived_first = (int*)malloc(sizeof(int)*num_of_job);

derived_second = (int*)malloc(sizeof(int)*num_of_job);

// 复制交换点前的基因

memcpy(derived_first, chromosome_first, sizeof(int)*(1+exchange_pos));

memcpy(derived_second, chromosome_second, sizeof(int)*(1+exchange_pos));

// 由两个亲本产生第一个子代

k = exchange_pos + 1;

for (i=0; i<num_of_job; ++i)

{

is_equal = 0;

for (j=0; j<=exchange_pos; ++j)

{

if (chromosome_second[i]==chromosome_first[j])

{

is_equal = 1;

break;

}

}

if (is_equal == 0)

{

derived_first[k] = chromosome_second[i];

++k;

}

}

// 由两个亲本产生第二个子代

k = exchange_pos + 1;

for (i=0; i<num_of_job; ++i)

{

is_equal = 0;

for (j=0; j<=exchange_pos; ++j)

{

if (chromosome_first[i]==chromosome_second[j])

{

is_equal = 1;

break;

}

}

if (is_equal == 0)

{

derived_second[k] = chromosome_first[i];

++k;

}

}

// 覆盖原始亲本

memcpy(chromosome_first, derived_first, sizeof(int)*num_of_job);

memcpy(chromosome_second, derived_second, sizeof(int)*num_of_job);

free(derived_first);

free(derived_second);

}

void reverse_gene(int *chromosome, int num_of_job)

{

int first_rev_pos; //第一倒位点

int second_rev_pos; //第二倒位点

int i, distance;

int temp;

first_rev_pos = rand() % num_of_job;

second_rev_pos = rand() % (num_of_job-first_rev_pos)+first_rev_pos;

distance = (second_rev_pos - first_rev_pos) / 2;

for (i=0; i<=distance; ++i)

{

temp = chromosome[first_rev_pos+i];

chromosome[first_rev_pos+i] = chromosome[second_rev_pos-i];

chromosome[second_rev_pos-i] = temp;

}

}

void gene_mutate(int *chromosome, int num_of_job)

{

int mutate_pos; // 变异点

int mutate_value; // 变异后基因值

int ex_pos; //与变异点的交换点

int i;

mutate_pos = rand() % num_of_job;

mutate_value = rand() % num_of_job + 1;

for (i=0; i<num_of_job; ++i)

{

if (chromosome[i] == mutate_value)

{

ex_pos = i;

break;

}

}

i = chromosome[ex_pos];

chromosome[ex_pos] = chromosome[mutate_pos];

chromosome[mutate_pos] = i;

}

void ERV_colony(int **colony, float pe, float pr, float pv, int num_of_job, int num_of_chromosomes)

{

int **tmp_colony;

int i;

int first, second;

tmp_colony = (int**)malloc(sizeof(int*)*num_of_chromosomes);

for (i=0; i<num_of_chromosomes; ++i)

{

tmp_colony[i] =(int*)malloc(sizeof(int)*num_of_job);

}

// copy

for (i=0; i<num_of_chromosomes; ++i)

{

memcpy(tmp_colony[i], colony[i], sizeof(int)*num_of_job);

}

for (i=0; i<num_of_chromosomes; i+=2)

{

first = rand() % num_of_chromosomes;

while (1)

{

second = rand() % num_of_chromosomes;

if (first != second)

break;

}

memcpy(colony[i], tmp_colony[first], sizeof(int)*num_of_job);

memcpy(colony[i+1], tmp_colony[second], sizeof(int)*num_of_job);

if (execute_probably(pe))

exchange_gene(colony[i],colony[i+1],num_of_job);

if (execute_probably(pr))

{

reverse_gene(colony[i], num_of_job);

reverse_gene(colony[i+1], num_of_job);

}

if (execute_probably(pv))

{

gene_mutate(colony[i], num_of_job);

gene_mutate(colony[i+1], num_of_job);

}

}

// free all resource

for (int i=0; i<num_of_chromosomes; ++i)

{

free(tmp_colony[i]);

}

free(tmp_colony);

}

下面是程序编译运行后的一种结果(已经在VC7.1,Dev-C++4.9.8.0上编译测试过)。输出为初始群体,0至第50代的平均效益(mean)

最差效益(max),最佳效益(min)。最后是最后一代群体的分配情况。

由于初始序列随机产生,且一般遗传算法往往存在难于收敛到最佳解的情况,本程序有时候也会无法收敛到最佳解。但是只要多运行几次,就可以获得最佳解序列。

最佳分配序列:5 2 3 4 1, 此时效益为17

Origin Colonies

5 3 2 4 1

5 2 1 4 3

2 5 4 1 3

2 3 5 4 1

1 2 4 5 3

1 3 2 4 5

5 4 3 2 1

3 1 4 2 5

5 3 4 1 2

5 1 3 4 2

Current benefit

mean:23 max:28 min:18

current gen : 1

mean: 21.8 max:29 min:18

current gen : 2

mean: 19.7 max:23 min:18

current gen : 3

mean: 19.8 max:24 min:17

current gen : 4

mean: 18.4 max:21 min:17

current gen : 5

mean: 18.2 max:21 min:17

current gen : 6

mean: 17.4 max:18 min:17

current gen : 7

mean: 17.8 max:22 min:17

current gen : 8

mean: 17.2 max:18 min:17

current gen : 9

mean: 17 max:17 min:17

current gen : 10

mean: 17.3 max:20 min:17

current gen : 11

mean: 17 max:17 min:17

current gen : 12

mean: 17.3 max:20 min:17

current gen : 13

mean: 18.8 max:27 min:17

current gen : 14

mean: 17.6 max:23 min:17

current gen : 15

mean: 17.5 max:20 min:17

current gen : 16

mean: 18.2 max:23 min:17

current gen : 17

mean: 17.5 max:22 min:17

current gen : 18

mean: 17 max:17 min:17

current gen : 19

mean: 17 max:17 min:17

current gen : 20

mean: 17.5 max:22 min:17

current gen : 21

mean: 17.6 max:20 min:17

current gen : 22

mean: 17 max:17 min:17

current gen : 23

mean: 17.8 max:22 min:17

current gen : 24

mean: 17.6 max:23 min:17

current gen : 25

mean: 17.5 max:22 min:17

current gen : 26

mean: 17 max:17 min:17

current gen : 27

mean: 17 max:17 min:17

current gen : 28

mean: 17 max:17 min:17

current gen : 29

mean: 17 max:17 min:17

current gen : 30

mean: 18.1 max:22 min:17

current gen : 31

mean: 17.8 max:20 min:17

current gen : 32

mean: 17 max:17 min:17

current gen : 33

mean: 17.6 max:23 min:17

current gen : 34

mean: 17.3 max:20 min:17

current gen : 35

mean: 17 max:17 min:17

current gen : 36

mean: 17 max:17 min:17

current gen : 37

mean: 17 max:17 min:17

current gen : 38

mean: 17 max:17 min:17

current gen : 39

mean: 18.1 max:23 min:17

current gen : 40

mean: 17.3 max:20 min:17

current gen : 41

mean: 17 max:17 min:17

current gen : 42

mean: 17 max:17 min:17

current gen : 43

mean: 17 max:17 min:17

current gen : 44

mean: 17.5 max:22 min:17

current gen : 45

mean: 17 max:17 min:17

current gen : 46

mean: 18.3 max:27 min:17

current gen : 47

mean: 17.9 max:20 min:17

current gen : 48

mean: 17 max:17 min:17

current gen : 49

mean: 17 max:17 min:17

current gen : 50

mean: 17 max:17 min:17

Laster Colony

5 2 3 4 1

5 2 3 4 1

5 2 3 4 1

5 2 3 4 1

5 2 3 4 1

5 2 3 4 1

5 2 3 4 1

5 2 3 4 1

5 2 3 4 1

5 2 3 4 1

参考文献:

[1] 计算机集成制造系统 主编 严新民 西北工业大学出版社 p110-p114

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有