C++ 用遗传算法解决TSP问题,旅行商问题

这也是人工智能实验的一个题目

这是一个很简陋的遗传算法版本,只有交叉(交配)

因为种群个体只有2个,所以就抛弃了选择复制

变异暂无

#include<iostream>

#include<fstream>

using namespace std;

float city_dis[4][4];

class individual

{

public:

int gene[5]; //个体基因,5个数字,0xxx0,从城市0开始出发,到0结束

float fitness; //适应度,取20.0/distance (这个20随便取的,重点是distance的倒数)

int distance; //计算当前基因(路线)下的总距离

individual(int gene0,int gene1,int gene2,int gene3,int gene4)

{//初始化基因

gene[0]=gene0;

gene[1]=gene1;

gene[2]=gene2;

gene[3]=gene3;

gene[4]=gene4;

//基因传递后执行update函数(计算fitness和distance)

update_info();

}

void set_new_gene(int *new_gene)

{

for(int i=1;i<4;++i)

{//设置新基因只会改变中间3个基因,所以循环从1到3

this->gene[i] = new_gene[i-1];//gene和传递进来到new_gene开始计数值不同

}

update_info();//更新个体fitness和distance

}

void update_info()

{//更新fitness和distance的函数

int new_dis = 0;

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

{

new_dis += city_dis[this->gene[i]][this->gene[i+1]];

}

this->distance = new_dis;

this->fitness = 20.0/this->distance;

}

};

class tsp

{

public:

int ROUTE_NUM; //城市数量,用于循环

int generation_counts; //迭代次数,控制循环结束时间

int best_route[5]; //存储目前最好的个体(路线)

int best_distance; //最好个体的路线距离

float best_fitness; //其适应度

individual *father1; //初始个体1(路线1

individual *father2; //初始个体2(路线2

tsp()

{

ROUTE_NUM = 5; //5个城市

generation_counts = 500; //迭代次数500次

memset(best_route,-1,5*sizeof(int));

best_distance = 0;

best_fitness = 0;

load_city_distance(); //从文件加载城市距离

father1 = new individual(0,2,1,3,0); //初始化个体1

//try rand father sequence //取消下面备注则会生成随机的基因给初始个体

// int rand1[3];

// get_random_nums(rand1,3);

// father1->set_new_gene(rand1);

father2 = new individual(0,1,3,2,0); //初始化个体2

// int rand2[3];

// get_random_nums(rand2,3);

// father2->set_new_gene(rand2);

}

~tsp()

{//析构函数

delete father1;

delete father2;

}

void start_generate()

{//迭代总函数

srand(time(NULL)); //取随机数用

while(--generation_counts >= 0) //

{

//cout<<generation_counts<<endl;

get_best_fornow(); //获取当前种群最好个体

switch_part_genes(); //交换两个体的随机2个基因,开始和结束的0基因不参加交换

}

}

void get_best_fornow()

{//判断当前种群是否比已有的best个体更优,有则替换

individual *now_the_best;

if(father1->fitness > father2->fitness)

{//找到两个个体最优,并用指针指向它

now_the_best = father1;

}

else

{

now_the_best = father2;

}

if(now_the_best->fitness > this->best_fitness)

{//better one will replace the original best individual

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

{

this->best_route[i] = now_the_best->gene[i];//替换基因

}

this->best_distance = now_the_best->distance; //替换distance

this->best_fitness = now_the_best->fitness; //替换fitness

}

}

void switch_part_genes()

{//switch 2 random genes in individual

int gene_place1[2];

int gene_place2[2];

get_random_nums(gene_place1,2);//生成1-3中2个不同随机数给place1

get_random_nums(gene_place2,2);//生成1-3中2个不同随机数给place2

//start to switch

swap_gene(gene_place1,gene_place2);//交换基因

father1->update_info();//更新个体信息

father2->update_info();

}

void swap_gene(int loc1[2],int loc2[2])

{ //loc1 is for father1;loc 2 for father 2

//用loc1中的2个father1基因位置来交换loc2中2个father2基因的位置

// cout<<loc1[0]<<" "<<loc1[1]<<endl;

// cout<<loc2[0]<<" "<<loc2[1]<<endl;

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

{ //father1[i] <-> father2[i]

int temp_father1_gene = father1->gene[loc1[i]];

father1->gene[loc1[i]] = father2->gene[loc2[i]];

father2->gene[loc2[i]] = temp_father1_gene;

}

clear_conflict(father1);//交换后可能出现冲突 比如01220这种序列,需要处理冲突

clear_conflict(father2);

}

void clear_conflict(individual *ptr)

{

int mapping[4]={0,2,3,1};//mapping映射 0->0 1->2 2->3 3->1 //01220就会映射为01320

int has_Conf_loc = has_conflict(ptr);

while(has_Conf_loc)

{

switch(has_Conf_loc)

{//根据冲突位置用映射消除冲突

case 1:

ptr->gene[1] = mapping[ptr->gene[2]];

break;

case 2:

ptr->gene[1] = mapping[ptr->gene[3]];

break;

case 3:

ptr->gene[3] = mapping[ptr->gene[3]];

break;

}

has_Conf_loc = has_conflict(ptr);

}

return;

}

int has_conflict(individual *one)

{ //可能冲突位置只有123,0和4固定为城市0,只要1和2、1和3、2和3都不冲突,即基因不冲突

//不同返回值用于快速定位冲突位置

if(one->gene[1] == one->gene[2])

return 1;

if(one->gene[1] == one->gene[3])

return 2;

if(one->gene[2] == one->gene[3])

return 3;

return 0;

}

bool get_random_nums(int *nums,int size)

{//给nums数组生成size个不同随机数

if(size <= 0)

{

return false;

}

if(size == 1)

{

nums[0] = rand()%3+1;//range 1-3

return true;

}

//size >= 2;

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

{//i is the target place

nums[i] = rand()%3+1;

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

{//j seeking the same number

if(nums[i] == nums[j])

{

nums[i] = rand()%3+1;

j=-1;

}

}

}

return true;

}

void print_best_route()

{

cout<<"BEST ROUTE:";

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

{

cout<<best_route[i]<<" ";

}

cout<<endl;

cout<<"DISTANCE:"<<this->best_distance<<endl;

cout<<"FITNESS:"<<this->best_fitness<<endl;

}

void load_city_distance()

{//从文件读取城市距离信息

char in_data[10];

ifstream in_stream;

in_stream.open("ds.txt",ios::in);

if(!in_stream.is_open())

return;

int j=0;

int k=0;

while(!in_stream.eof())

{

in_stream.getline(in_data,10);

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

{

if(in_data[i]>= '0' && in_data[i] <= '9')

{

city_dis[j][k++] = in_data[i]-'0';

if(k==4)

{

k=0;

++j;

break;

}

}

}

}

in_stream.close();

}

};

int main()

{

tsp tsp_demo;

tsp_demo.start_generate();

tsp_demo.print_best_route();

return 0;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

附测试截图

ds.txt 文件内容

0 1 3 4

1 0 2 5

3 2 0 3

4 5 3 0

C++ 用遗传算法解决TSP问题,旅行商问题