/*************************************************************** //给出DATA30.DAT 测试数据 //(x, y)表示城市的坐标 54 62 蚁群算法(ACA)解TSP代码,布布扣,bubuko.com
* 程序名称: 针对TSP组合优化问题人工蚁群算法(ACA_TSP)
* 编译环境: Visual C++ 6.0
* 交流方式: Email (junh_cs@126.com)
***************************************************************/
#include
#include
#include
#include
#include
/**************************************************************/
#define CITY_NUM 30 //表示城市数目
#define ANT_NUM 10 //表示蚂蚁数目
#define ITERITIVE_NUM 400 //表示迭代的次数
#define POSITION_DIM 2 //表示城市坐标的维度
#define FCITY_INDEX 0 //用来表示初始城市的下标(目前只能等于0,后期改进)
// 下面的参数选取对结果有很大的影响
#define AILFA 5 //用来表示信息素在计算转移概率的重要性
#define BETA 4 //用来表示能见度(距离信息)在计算转移概率的重要性
#define VOLATIE_FACTOR 0.08 //挥发因子在0到1之间
#define INIT_PHEROMONE 0.1 //每个边的初始信息素含量
/*
//在DATA30.dat上调的参数
#define CITY_NUM 30 //表示城市数目
#define ANT_NUM 10 //表示蚂蚁数目
#define ITERITIVE_NUM 400 //表示迭代的次数
#define POSITION_DIM 2 //表示城市坐标的维度
#define FCITY_INDEX 0 //用来表示初始城市的下标(目前只能等于0,后期改进)
// 下面的参数选取对结果有很大的影响
#define AILFA 4 //用来表示信息素在计算转移概率的重要性
#define BETA 3 //用来表示能见度(距离信息)在计算转移概率的重要性
#define VOLATIE_FACTOR 0.08 //挥发因子在0到1之间
#define INIT_PHEROMONE 0.1 //每个边的初始信息素含量
//0->17->1->9->13->27->6->16->21->11->24->3->7->8->28->15->14->22->20->12->10->4->29->23->5->25->18->26->19->2->0
//total_distance = 420.794632
*/
/**************************************************************/
// 定义个全局变量
double city_pos[CITY_NUM][POSITION_DIM]; //存储city的坐标信息
double pheromone[CITY_NUM][CITY_NUM]; //存储cityA到cityB边的信息素
double city_dis[CITY_NUM][CITY_NUM]; //存储cityA到cityB的距离,即:能见度
int local_road_info[CITY_NUM+1]; //存储此次最好(最短)路径 (默认都是文件读入的编号开始)
int global_road_info[CITY_NUM+1]; //存储此次最好(最短)路径 (默认都是文件读入的编号开始)
double local_road_dis = 9999999999; //存储最好(最短)路径长度
double global_road_dis = 9999999999; //存储最好(最短)路径长度
int tag_old[ANT_NUM][CITY_NUM]; //存储每只蚂蚁走过了哪些路,走过用1,没走过用0
/**************************************************************/
//函数预定义区域
double calculate_Pij(int ant, int cityA, int cityB); //计算ant从cityA转移cityB概率
void initialize(); //初始化环境
void init_tag_old(); //初始化tag_old变量
double odistance(double *a, double *b, int vector_len); //计算两个城市之间距离
void findOneTimeFood(); //模拟人工蚁群一次找食物的过程
void update_pheromone_matrix(); //根据global_road信息跟新信息素
double rand_select_value(double under, double upper); //从[under, upper]之间产生一个随机数
int is_ij_int_global_road(int i, int j); //判断ij在不在全局最优路径中
void search_short_road(); //找到全局最优的路径
void print_cmd(); //在命令行端输出最短路径和路径长度
void print_file(double seconds, char* file_path); //在文件中输出最短路径和路径长度
/**************************************************************/
void main(){
int k;
int i;
FILE *fp;
float x;
float y;
clock_t start;
clock_t end;
srand(time(NULL)); //初始化随机种子
for (k = 0; k <20; k++){
// read city position (x, y)
fp=fopen("DATA30.dat","r");
for(i = 0; i
printf("%f, %f\n", x, y);
city_pos[i][0]= x;
city_pos[i][1]= y;
}
fclose(fp);
start=clock(); //记录程序开始运行的时间
initialize();
search_short_road();
end=clock(); //记录程序运行结束的时间
print_file(1.0*(end-start)/1000, "实验结果.txt");
}
}
/**************************************************************
* @function: 初始化变量,构建初始化状态
**************************************************************/
void initialize(){
int i;
int j;
// average the pheromone value to per edge
// calculate the distance of each edge
for (i = 0; i
for (j = 0; j city_dis[i][j] = odistance(city_pos[i], city_pos[j], POSITION_DIM);
city_dis[j][i] = city_dis[i][j]; //这里的距离都是相等的
pheromone[i][j] = pheromone[j][i] = INIT_PHEROMONE; //约等于0
}
}
// initialize the tag_old array
init_tag_old();
global_road_dis = 9999999999;
local_road_dis = 9999999999;
}
/**************************************************************
* @function: 初始化tag_old变量
**************************************************************/
void init_tag_old(){
int i;
int j;
for (i = 0; i
for (j = 1; j
}
}
}
/**************************************************************
* @function: 找到最好的路径
**************************************************************/
void search_short_road(){
int i;
int times = 0;
while (times
findOneTimeFood();
if (local_road_dis
for (i = 0; i
}
}//end_if
printf("the %d iteritive: \n", times);
print_cmd();
// update the pheromone matrix
update_pheromone_matrix();
times++;
}//end_while
}
/**************************************************************
* @function: 更新信息素矩阵
**************************************************************/
void update_pheromone_matrix(){
int i;
int j;
for (i = 0; i
pheromone[i][j] = (1-VOLATIE_FACTOR)*pheromone[i][j]
+ VOLATIE_FACTOR / global_road_dis;
}else{ //不在全局最优路径中
pheromone[i][j] = (1-VOLATIE_FACTOR)*pheromone[i][j];
}
}
}
}
/**************************************************************
* @function: 判断ij边在不在global_road中
**************************************************************/
int is_ij_int_global_road(int i, int j){
int k;
int ans = 0;
for (k = 0; k
&& j == global_road_info[k+1]){
ans = 1;
break;
}
}
return ans;
}
/**************************************************************
* @function: 模拟人工蚁群一次找食物的过程 (还是需要修改的)
**************************************************************/
void findOneTimeFood(){
int i;
int j;
int k;
int next_city; //可以表示当前蚂蚁选择的下一个城市下标
double next_city_pro[CITY_NUM]; //存储每一只蚂蚁去下一个城市的概率
int now_road[CITY_NUM+1]; //存储每一只蚂蚁找到的路径
double now_road_dis;
init_tag_old(); //在每次出动的时候,历史信息都将初始化
local_road_dis = 9999999999; //初始化local_road_diss
for (i = 0; i
now_road[0] = 0;
now_road_dis = 0.0;
for (j = 1; j
// 并以直方图累加的形式存储在next_city_pro中
next_city_pro[0] = 0.0;
for (k = 1; k
next_city_pro[k] = next_city_pro[k-1] + tmp;
}
// 产生一个随机数看其落在哪一个区间
double rd = rand_select_value(0.0, 1.0-0.000001); //-0.000001? 确保每个城市都能走到
for (next_city = 1; next_city
}
}
tag_old[i][next_city] = 1;
now_road[j] = next_city;
now_road_dis += city_dis[now_road[j-1]][next_city];
}
now_road[CITY_NUM] = 0;
now_road_dis += city_dis[now_road[next_city]][0];
if (now_road_dis
for (k = 0; k
}
}
}
}
/**************************************************************
* @function: 计算ant从cityA转移cityB概率
**************************************************************/
double calculate_Pij(int ant, int now_city, int aim_city){
double ans = 0.0;
double sum = 0.0;
int i;
if (0 == tag_old[ant][aim_city]){
for (i = 0; i
sum += (pow(pheromone[now_city][i], AILFA)
*pow(1/city_dis[now_city][i], BETA));
}
}
double tmp = pow(pheromone[now_city][aim_city], AILFA)*pow(1/city_dis[now_city][aim_city], BETA);
ans = tmp/sum;
}
return ans;
}
/**************************************************************
* @function: 计算两个向量之间的距离
* @notice : 两个向量a与b必须是vector_len长度
**************************************************************/
double odistance(double *a, double *b, int vector_len){
double ans = 0;
int i;
for (i = 0; i
}
ans = sqrt(ans);
return ans;
}
/**************************************************************
* @function: 该函数是在[under, upper]区间中随机
* 选择一个值
**************************************************************/
double rand_select_value(double under, double upper){
if(under>upper) {
printf("\nerror:\t[%d, %d] is invalid region!", under, upper);
exit(1);
}
double lamta = (double)rand()/(RAND_MAX);
return (under+(upper-under)*lamta);
}
/**************************************************************
* @function: 该函数主要是判断两个等长的a向量和b向量是不是一样的
* 如果一样了返回1, 否则返回0
**************************************************************/
int is_same_vector(double* a, double* b, int len){
int ans = 1, i;
for (i = 0; i
ans = 0;
break;
}
}
return ans;
}
/**************************************************************
* @function: 在命令行输出伪次优路径,和路径总长度
**************************************************************/
void print_cmd(){
int i;
for (i = 0; i
}
printf("%d\ntotal_distance = %.6f\n", global_road_info[CITY_NUM], global_road_dis);
}
/**************************************************************
* @function: 在文件中出伪次优路径,和路径总长度
**************************************************************/
void print_file(double seconds, char* file_path){
FILE *fp = fopen(file_path, "a");
int i;
for (i = 0; i
}
fprintf(fp, "%d\n总距离为: %.6f\n", global_road_info[CITY_NUM], global_road_dis);
fprintf(fp, "%d次迭代共花: %.2f秒\n", ITERITIVE_NUM, seconds);
fclose(fp);
}
58 69
71 71
45 21
25 62
37 84
83 46
41 26
44 35
64 60
22 60
62 32
18 54
68 58
18 40
24 42
91 38
54 67
74 78
83 69
4 50
82 7
13 40
2 99
58 35
41 94
87 76
71 44
25 38
7 64