ABC算法求解TSP问题的C++实现
1、输入数据文件:bayg29.tsp
1 1150.0 1760.0
2 630.0 1660.0
3 40.0 2090.0
4 750.0 1100.0
5 750.0 2030.0
6 1030.0 2070.0
7 1650.0 650.0
8 1490.0 1630.0
9 790.0 2260.0
10 710.0 1310.0
11 840.0 550.0
12 1170.0 2300.0
13 970.0 1340.0
14 510.0 700.0
15 750.0 900.0
16 1280.0 1200.0
17 230.0 590.0
18 460.0 860.0
19 1040.0 950.0
20 590.0 1390.0
21 830.0 1770.0
22 490.0 500.0
23 1840.0 1240.0
24 1260.0 1500.0
25 1280.0 790.0
26 490.0 2130.0
27 1460.0 1420.0
28 1260.0 1910.0
29 360.0 1980.0
2、头文件
#include <iostream>
#include <string>
#include <fstream>
#include <random>
#include <time.h>
using namespace std;
3、所需的类
程序中用到了城市类City、包含城市的地图类Graph、蜜蜂类Bee和人工蜂群算法类ABC
3.1 城市类City
class City
{
public:
string name;//城市名称
double x, y;//城市点的二维坐标
void shuchu()
{
std::cout << name + ":" << "(" << x << "," << y << ")" << endl;
}
};
3.2 包含城市的地图类Graph
class Graph
{
public:
int Citycount;
City *city;//城市数组
double distance[citycount][citycount];//城市间的距离矩阵
void Readcoordinatetxt(string txtfilename)//读取城市坐标文件的函数
{
Citycount = citycount;
city = new City[Citycount];
ifstream myfile(txtfilename, ios::in);
double x = 0, y = 0;
int z = 0;
if (!myfile.fail())
{
int i = 0;
while (!myfile.eof() && (myfile >> z >> x >> y))
{
city[i].name = to_string(_Longlong(z));//城市名称转化为字符串
city[i].x = x; city[i].y = y;
i++;
}
}
else
cout << "文件不存在";
myfile.close();//计算城市距离矩阵
for (int i = 0; i < citycount; i++)
for (int j = 0; j < citycount; j++)
{
distance[i][j] = sqrt((pow((city[i].x - city[j].x), 2) + pow((city[i].y - city[j].y), 2)) / 10.0);//计算城市ij之间的伪欧式距离
if (round(distance[i][j] < distance[i][j]))distance[i][j] = round(distance[i][j]) + 1;
else distance[i][j] = round(distance[i][j]);
}
}
void shuchu()
{
cout << "城市名称 " << "坐标x" << " " << "坐标y" << endl;
for (int i = 0; i < citycount; i++)
city[i].shuchu();
cout << "距离矩阵: " << endl;
for (int i = 0; i < citycount; i++)
{
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
std::cout << distance[i][j] << endl;
else
std::cout << distance[i][j] << " ";
}
}
}
};
3.3 蜜蜂类Bee
class Bee
{
public:
int dimension;//变量的维数
int *x;
double fitdegreevalue = 0;
double selectprobability = 0;
int limitcishu = 0;
void Init(int Dimension)
{
dimension = Dimension;
x = new int[dimension];
for (int j = 0; j < citycount; j++)
{
*(x + j) = round(xmin + u(random)*(xmax - xmin));//随机初始化可行解
}
Adjuxt_validParticle(x);//对蜜源路径进行有效性调整,确保是TSP问题的一个可行解
}
void shuchu()
{
for (int j = 0; j < dimension; j++)
{
if (j == dimension - 1)std::cout << x[j] << ")"<< endl;
else if (j == 0)
std::cout << "(" << x[j] << ", ";
else
std::cout << x[j] << ", ";
}
}
};
3.4 人工蜂群算法类ABC
class ABC
{
public:
Bee *miyuan, bestmiyuan, *employedbee, *onlookerbee;//蜜源、最好蜜源、雇佣蜂、观察蜂
int SN;//雇佣蜂的数量、蜜源的数量、观察蜂的数量相等
int Dimension;//可行解的维数
int MCN;//终止代数
int Limit;//为防止算法陷入局部最优,蜜源最大改进次数
void Init(int sn, int dimension, int mcn, int limit)
{
SN = sn;
Dimension = dimension;
MCN = mcn;
Limit = limit;
miyuan = new Bee[SN];
employedbee = new Bee[SN];
onlookerbee = new Bee[SN];
for (int i = 0; i < SN; i++)
{
(miyuan + i)->Init(Dimension);
double beefunvalue = CalculateFitValue(*(miyuan + i));
(miyuan + i)->fitdegreevalue = CalculateFitDegree(beefunvalue);
(employedbee + i)->Init(Dimension);
double employedbeefunvalue = CalculateFitValue(*(employedbee + i));
(employedbee + i)->fitdegreevalue = CalculateFitDegree(employedbeefunvalue);
(onlookerbee + i)->Init(Dimension);
double onlookerbeefunvalue = CalculateFitValue(*(onlookerbee + i));
(onlookerbee + i)->fitdegreevalue = CalculateFitDegree(onlookerbeefunvalue);
}
bestmiyuan.Init(Dimension);//最好蜜源初始化
for (int j = 0; j < Dimension; j++)
{
bestmiyuan.x[j] = miyuan->x[j];
}
bestmiyuan.fitdegreevalue = miyuan->fitdegreevalue;
}
double CalculateFitValue(Bee be)//适应值计算函数,即计算路径长度
{
double funvalue = 0;
for (int i = 0; i < citycount - 1; i++)
funvalue += Map_City.distance[be.x[i]-1][be.x[i + 1]-1];
funvalue += Map_City.distance[be.x[citycount - 1]-1][be.x[0]-1];
return funvalue;
}
double CalculateFitDegree(double fi)//计算适应度的函数
{
double fitnessdu = 0;
if (fi > 0)
fitnessdu = 1.0 / (1 + fi);
else
fitnessdu = 1 + abs(fi);
return fitnessdu;
}
void EmployedBeeOperate()//雇佣蜂操作函数
{
std::uniform_int_distribution<int> uD(1, Dimension); //随机数分布对象
std::uniform_int_distribution<int> uSN(1, SN); //随机数分布对象
for (int i = 0; i < SN; i++)
{
for (int j = 0; j < Dimension; j++)//雇佣峰利用先前的蜜源信息寻找新的蜜源
{
(employedbee + i)->x[j] = (miyuan + i)->x[j];
}
int k, jie;//随机生成且 k≠i k∈[1,SN]
jie = uD(random) - 1;//jie为【1,Dimension】上的随机数
double φ = u1(random);//φ表示[-1,1]之间的随机数
while (true)
{
k = uSN(random) - 1;
if (k != i)break;
}
(employedbee + i)->x[jie] = (miyuan + i)->x[jie] + φ*((miyuan + i)->x[jie] - (miyuan + k)->x[jie]);//搜索新蜜源
//保证蜜源位置不越界
if ((employedbee + i)->x[jie] > xmax) (employedbee + i)->x[jie] = xmax;
else if ((employedbee + i)->x[jie] < xmin) (employedbee + i)->x[jie] = xmin;
Adjuxt_validParticle((employedbee + i)->x);//对蜜源路径进行有效性调整,确保是TSP问题的一个可行解
(employedbee + i)->fitdegreevalue = CalculateFitDegree(CalculateFitValue(*(employedbee + i)));//计算适应度值 //雇佣蜂根据贪心策略选择蜜源
if (CalculateFitValue(*(employedbee + i)) < CalculateFitValue(*(miyuan + i)))
{
for (int j = 0; j < Dimension; j++)
(miyuan + i)->x[j] = (employedbee + i)->x[j];
(miyuan + i)->limitcishu = 0;
(miyuan + i)->fitdegreevalue = (employedbee + i)->fitdegreevalue;
}
else
(miyuan + i)->limitcishu++;//蜜源未改进次数加一
}
}
void CalculateProbability()//计算蜜源概率的函数
{
for (int i = 0; i < SN; i++)
{
(miyuan + i)->fitdegreevalue = CalculateFitDegree(CalculateFitValue(*(miyuan + i)));
}
double sumfitdegreevalue = 0;
for (int i = 0; i < SN; i++)
{
sumfitdegreevalue += (miyuan + i)->fitdegreevalue;
}
for (int i = 0; i < SN; i++)
{
(miyuan + i)->selectprobability = (miyuan + i)->fitdegreevalue / sumfitdegreevalue;
}
}
void OnLookerBeeOperate()//观察蜂操作
{
std::uniform_int_distribution<int> uD(1, Dimension); //随机数分布对象
std::uniform_int_distribution<int> uSN(1, SN); //随机数分布对象
int m = 0;
while (m < SN)//为所有的观察蜂按照概率选择蜜源并搜索新蜜源,计算新蜜源适应值
{
double m_choosedprobability = u(random);//0~1之间的随机数
for (int i = 0; i < SN; i++)
{
if (m_choosedprobability < (miyuan + i)->selectprobability)
{
int k, jie;//随机生成且 k≠i k∈[1,SN]
jie = uD(random) - 1;//jie为【1,Dimension】上的随机数
double φ = u1(random);//φ表示[-1,1]之间的随机数
while (true)
{
k = uSN(random) - 1;
if (k != i)break;
}
for (int j = 0; j < Dimension; j++)
(onlookerbee + m)->x[j] = (miyuan + i)->x[j];
(onlookerbee + m)->x[jie] = (miyuan + i)->x[jie] + φ*((miyuan + i)->x[jie] - (miyuan + k)->x[jie]);//搜索新蜜源
if ((onlookerbee + m)->x[jie] > xmax) (onlookerbee + m)->x[jie] = xmax;
else if ((onlookerbee + m)->x[jie] < xmin) (onlookerbee + m)->x[jie] = xmin;//判断是否越界
Adjuxt_validParticle((onlookerbee + m)->x);//对蜜源路径进行有效性调整,确保是TSP问题的一个可行解
(onlookerbee + m)->fitdegreevalue = CalculateFitDegree(CalculateFitValue(*(onlookerbee + m)));
//贪心策略选择蜜源
if (CalculateFitValue(*(onlookerbee + m)) < CalculateFitValue(*(miyuan + i)))
{
for (int j = 0; j < Dimension; j++)
(miyuan + i)->x[j] = (onlookerbee + m)->x[j];
(miyuan + i)->fitdegreevalue = (onlookerbee + m)->fitdegreevalue;
}
else
(miyuan + i)->limitcishu++;
m++;
}break;
}
}
}
void ScoutBeeOperate()//侦查蜂操作,决定蜜源是否放弃,并随机产生新位置替代原蜜源
{
for (int i = 0; i < SN; i++)
{
if ((miyuan + i)->limitcishu >= Limit)
{
for (int j = 0; j < Dimension; j++)
{
(miyuan + i)->x[j] = round(xmin + u(random)*(xmax - xmin));//随机初始化可行解;//随机产生可行解
}
Adjuxt_validParticle((miyuan + i)->x);
(miyuan + i)->limitcishu = 0;
(miyuan + i)->fitdegreevalue = CalculateFitDegree(CalculateFitValue(*(miyuan + i)));
}
}
}
void SaveBestMiyuan()//记录最优解的函数
{
for (int i = 0; i < SN; i++)
{
if (CalculateFitValue(*(miyuan + i)) < CalculateFitValue(bestmiyuan))
{
for (int j = 0; j < Dimension; j++)
bestmiyuan.x[j] = (miyuan + i)->x[j];
}
}
}
void shuchumiyuan()
{
for (int i = 0; i < SN; i++)
{
std::cout << "蜜源" << i + 1<<"->";
for (int j = 0; j < Dimension; j++)
{
if (j == Dimension - 1)std::cout << (miyuan + i)->x[j] <<")对应的距离为: "<<CalculateFitValue(*(miyuan+i))<< endl;
else if(j==0)
std::cout <<"("<< (miyuan + i)->x[j] << ", ";
else
std::cout << (miyuan + i)->x[j] << ", ";
}
}
}
void ShuchuBestmiyuan()
{
for (int j = 0; j < Dimension; j++)
{
if (j == Dimension - 1) std::cout << bestmiyuan.x[j] << ")" << "对应的距离为:" << CalculateFitValue(bestmiyuan) << endl;
else if (j == 0) std::cout << "(" << bestmiyuan.x[j] << ",";
else std::cout << bestmiyuan.x[j] << ",";
}
}
void DoABC(int sn, int dimension, int mcn, int limit,string filename)//运行人工蜂群算法的函数
{
ofstream outfile;
outfile.open("result.txt", ios::trunc);
Map_City.Readcoordinatetxt(filename);
Map_City.shuchu();
outfile << "城市名称 " << "坐标x" << " " << "坐标y" << endl;
for (int i = 0; i < citycount; i++)
outfile << Map_City.city[i].name << " " << Map_City.city[i].x << " " << Map_City.city[i].y << endl;
outfile << "距离矩阵: " << endl;
for (int i = 0; i < citycount; i++)
{
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << Map_City.distance[i][j] << endl;
else
outfile << Map_City.distance[i][j] << " ";
}
}
Init(sn, dimension, mcn, limit);//初始化
shuchumiyuan();
outfile << "初始化后的蜜源如下:" << endl;
for (int i = 0; i < SN; i++)
{
outfile << "蜜源" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (miyuan + i)->x[j] << ") = " << CalculateFitValue(*(miyuan + i)) << endl;
else if (j == 0)
outfile << "f(" << (miyuan + i)->x[j] << ",";
else
outfile << (miyuan + i)->x[j] << ",";
}
}
SaveBestMiyuan();//保存最好蜜源
ShuchuBestmiyuan();
for (int k = 0; k < MCN; k++)
{
EmployedBeeOperate();
CalculateProbability();
OnLookerBeeOperate();
SaveBestMiyuan();
ScoutBeeOperate();
SaveBestMiyuan();
std::cout << "第" << k + 1 << "次迭代的最优解为:";
ShuchuBestmiyuan();
outfile << "第"<<k+1<<"次迭代后的蜜源如下:" << endl;
for (int i = 0; i < SN; i++)
{
outfile << "蜜源" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (miyuan + i)->x[j] << ") = " << CalculateFitValue(*(miyuan + i)) << endl;
else if (j == 0)
outfile << "f(" << (miyuan + i)->x[j] << ",";
else
outfile << (miyuan + i)->x[j] << ",";
}
}
outfile << "第" << k + 1 << "次迭代的最优蜜源为:";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << bestmiyuan.x[j] << ") = " << CalculateFitValue(bestmiyuan) << endl;
else if (j == 0)
outfile << "f(" << bestmiyuan.x[j] << ",";
else
outfile << bestmiyuan.x[j] << ",";
}
}
outfile.close();
}
};
4、自定义函数
自定义的函数有两个:四舍五入取整函数、蜜源路径有效性调整函数
4.1 四舍五入取整函数
double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
4.2 调整蜜源路径有效性的函数
void Adjuxt_validParticle(int x[citycount])//调整蜜源路径有效性的函数,使得蜜源的位置符合TSP问题解的一个排列
{
int route[citycount];//1-citycount
bool flag[citycount];//对应route数组中是否在位置中存在的数组,参考数组为route
int biaoji[citycount];//对每个元素进行标记的数组,参考数组为粒子位置x
for (int j = 0; j < citycount; j++)
{
route[j] = j + 1;
flag[j] = false;
biaoji[j] = 0;
}
//首先判断位置中是否有某个城市且唯一,若有且唯一,则对应flag的值为true,
for (int j = 0; j < citycount; j++)
{
int num = 0;
for (int k = 0; k < citycount; k++)
{
if (x[k] == route[j])
{
biaoji[k] = 1;//说明k号元素对应的城市在route中,并且是第一次出现才进行标记
num++; break;
}
}
if (num == 0) flag[j] = false;//路线中没有route[j]这个城市
else if (num == 1) flag[j] = true;//路线中有route[j]这个城市
}
for (int k = 0; k < citycount; k++)
{
if (flag[k] == false)//路线中没有route[k]这个城市,需要将这个城市加入到路线中
{
int i = 0;
for (; i < citycount; i++)
{
if (biaoji[i] != 1)break;
}
x[i] = route[k];//对于标记为0的进行替换
biaoji[i] = 1;
}
}
}
5、全局变量
const int citycount = 29;
double xmax = citycount, xmin = 1;
std::default_random_engine random((unsigned int)time(NULL));
std::uniform_real_distribution<double> u(0, 1); //随机数分布对象
std::uniform_real_distribution<double> u1(-1, 1); //随机数分布对象
Graph Map_City;//定义全局对象图,放在Graph类后
6、主函数
int main()
{
system("mode con cols=200");
system("color fc");
std::cout << "人工蜂群算法求解TSP旅行商问题!" << endl;
ABC abc;
abc.DoABC(50, citycount, 200, 20, "E:\\计算智能代码\\ABC_TSP\\ABC_TSP\\bayg29.tsp");
system("pause");
return 0;
}
7、运行结果
7.1 控制台结果
7.2 生成的result.txt文件结果
8、MATLAB绘制最优路径结果
附录(完整代码)
#include <iostream>
#include <string>
#include <fstream>
#include <random>
#include <time.h>
using namespace std;
const int citycount = 29;
double xmax = citycount, xmin = 1;
std::default_random_engine random((unsigned int)time(NULL));
std::uniform_real_distribution<double> u(0, 1); //随机数分布对象
std::uniform_real_distribution<double> u1(-1, 1); //随机数分布对象
class City
{
public:
string name;//城市名称
double x, y;//城市点的二维坐标
void shuchu()
{
std::cout << name + ":" << "(" << x << "," << y << ")" << endl;
}
};
class Graph
{
public:
int Citycount;
City *city;//城市数组
double distance[citycount][citycount];//城市间的距离矩阵
void Readcoordinatetxt(string txtfilename)//读取城市坐标文件的函数
{
Citycount = citycount;
city = new City[Citycount];
ifstream myfile(txtfilename, ios::in);
double x = 0, y = 0;
int z = 0;
if (!myfile.fail())
{
int i = 0;
while (!myfile.eof() && (myfile >> z >> x >> y))
{
city[i].name = to_string(_Longlong(z));//城市名称转化为字符串
city[i].x = x; city[i].y = y;
i++;
}
}
else
cout << "文件不存在";
myfile.close();//计算城市距离矩阵
for (int i = 0; i < citycount; i++)
for (int j = 0; j < citycount; j++)
{
distance[i][j] = sqrt((pow((city[i].x - city[j].x), 2) + pow((city[i].y - city[j].y), 2)) / 10.0);//计算城市ij之间的伪欧式距离
if (round(distance[i][j] < distance[i][j]))distance[i][j] = round(distance[i][j]) + 1;
else distance[i][j] = round(distance[i][j]);
}
}
void shuchu()
{
cout << "城市名称 " << "坐标x" << " " << "坐标y" << endl;
for (int i = 0; i < citycount; i++)
city[i].shuchu();
cout << "距离矩阵: " << endl;
for (int i = 0; i < citycount; i++)
{
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
std::cout << distance[i][j] << endl;
else
std::cout << distance[i][j] << " ";
}
}
}
};
Graph Map_City;//定义全局对象图,放在Graph类后
double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
void Adjuxt_validParticle(int x[citycount])//调整蜜源路径有效性的函数,使得蜜源的位置符合TSP问题解的一个排列
{
int route[citycount];//1-citycount
bool flag[citycount];//对应route数组中是否在位置中存在的数组,参考数组为route
int biaoji[citycount];//对每个元素进行标记的数组,参考数组为粒子位置x
for (int j = 0; j < citycount; j++)
{
route[j] = j + 1;
flag[j] = false;
biaoji[j] = 0;
}
//首先判断位置中是否有某个城市且唯一,若有且唯一,则对应flag的值为true,
for (int j = 0; j < citycount; j++)
{
int num = 0;
for (int k = 0; k < citycount; k++)
{
if (x[k] == route[j])
{
biaoji[k] = 1;//说明k号元素对应的城市在route中,并且是第一次出现才进行标记
num++; break;
}
}
if (num == 0) flag[j] = false;//路线中没有route[j]这个城市
else if (num == 1) flag[j] = true;//路线中有route[j]这个城市
}
for (int k = 0; k < citycount; k++)
{
if (flag[k] == false)//路线中没有route[k]这个城市,需要将这个城市加入到路线中
{
int i = 0;
for (; i < citycount; i++)
{
if (biaoji[i] != 1)break;
}
x[i] = route[k];//对于标记为0的进行替换
biaoji[i] = 1;
}
}
}
class Bee
{
public:
int dimension;//变量的维数
int *x;
double fitdegreevalue = 0;
double selectprobability = 0;
int limitcishu = 0;
void Init(int Dimension)
{
dimension = Dimension;
x = new int[dimension];
for (int j = 0; j < citycount; j++)
{
*(x + j) = round(xmin + u(random)*(xmax - xmin));//随机初始化可行解
}
Adjuxt_validParticle(x);//对蜜源路径进行有效性调整,确保是TSP问题的一个可行解
}
void shuchu()
{
for (int j = 0; j < dimension; j++)
{
if (j == dimension - 1)std::cout << x[j] << ")"<< endl;
else if (j == 0)
std::cout << "(" << x[j] << ", ";
else
std::cout << x[j] << ", ";
}
}
};
class ABC
{
public:
Bee *miyuan, bestmiyuan, *employedbee, *onlookerbee;//蜜源、最好蜜源、雇佣蜂、观察蜂
int SN;//雇佣蜂的数量、蜜源的数量、观察蜂的数量相等
int Dimension;//可行解的维数
int MCN;//终止代数
int Limit;//为防止算法陷入局部最优,蜜源最大改进次数
void Init(int sn, int dimension, int mcn, int limit)
{
SN = sn;
Dimension = dimension;
MCN = mcn;
Limit = limit;
miyuan = new Bee[SN];
employedbee = new Bee[SN];
onlookerbee = new Bee[SN];
for (int i = 0; i < SN; i++)
{
(miyuan + i)->Init(Dimension);
double beefunvalue = CalculateFitValue(*(miyuan + i));
(miyuan + i)->fitdegreevalue = CalculateFitDegree(beefunvalue);
(employedbee + i)->Init(Dimension);
double employedbeefunvalue = CalculateFitValue(*(employedbee + i));
(employedbee + i)->fitdegreevalue = CalculateFitDegree(employedbeefunvalue);
(onlookerbee + i)->Init(Dimension);
double onlookerbeefunvalue = CalculateFitValue(*(onlookerbee + i));
(onlookerbee + i)->fitdegreevalue = CalculateFitDegree(onlookerbeefunvalue);
}
bestmiyuan.Init(Dimension);//最好蜜源初始化
for (int j = 0; j < Dimension; j++)
{
bestmiyuan.x[j] = miyuan->x[j];
}
bestmiyuan.fitdegreevalue = miyuan->fitdegreevalue;
}
double CalculateFitValue(Bee be)//适应值计算函数,即计算路径长度
{
double funvalue = 0;
for (int i = 0; i < citycount - 1; i++)
funvalue += Map_City.distance[be.x[i]-1][be.x[i + 1]-1];
funvalue += Map_City.distance[be.x[citycount - 1]-1][be.x[0]-1];
return funvalue;
}
double CalculateFitDegree(double fi)//计算适应度的函数
{
double fitnessdu = 0;
if (fi > 0)
fitnessdu = 1.0 / (1 + fi);
else
fitnessdu = 1 + abs(fi);
return fitnessdu;
}
void EmployedBeeOperate()//雇佣蜂操作函数
{
std::uniform_int_distribution<int> uD(1, Dimension); //随机数分布对象
std::uniform_int_distribution<int> uSN(1, SN); //随机数分布对象
for (int i = 0; i < SN; i++)
{
for (int j = 0; j < Dimension; j++)//雇佣峰利用先前的蜜源信息寻找新的蜜源
{
(employedbee + i)->x[j] = (miyuan + i)->x[j];
}
int k, jie;//随机生成且 k≠i k∈[1,SN]
jie = uD(random) - 1;//jie为【1,Dimension】上的随机数
double φ = u1(random);//φ表示[-1,1]之间的随机数
while (true)
{
k = uSN(random) - 1;
if (k != i)break;
}
(employedbee + i)->x[jie] = (miyuan + i)->x[jie] + φ*((miyuan + i)->x[jie] - (miyuan + k)->x[jie]);//搜索新蜜源
//保证蜜源位置不越界
if ((employedbee + i)->x[jie] > xmax) (employedbee + i)->x[jie] = xmax;
else if ((employedbee + i)->x[jie] < xmin) (employedbee + i)->x[jie] = xmin;
Adjuxt_validParticle((employedbee + i)->x);//对蜜源路径进行有效性调整,确保是TSP问题的一个可行解
(employedbee + i)->fitdegreevalue = CalculateFitDegree(CalculateFitValue(*(employedbee + i)));//计算适应度值 //雇佣蜂根据贪心策略选择蜜源
if (CalculateFitValue(*(employedbee + i)) < CalculateFitValue(*(miyuan + i)))
{
for (int j = 0; j < Dimension; j++)
(miyuan + i)->x[j] = (employedbee + i)->x[j];
(miyuan + i)->limitcishu = 0;
(miyuan + i)->fitdegreevalue = (employedbee + i)->fitdegreevalue;
}
else
(miyuan + i)->limitcishu++;//蜜源未改进次数加一
}
}
void CalculateProbability()//计算蜜源概率的函数
{
for (int i = 0; i < SN; i++)
{
(miyuan + i)->fitdegreevalue = CalculateFitDegree(CalculateFitValue(*(miyuan + i)));
}
double sumfitdegreevalue = 0;
for (int i = 0; i < SN; i++)
{
sumfitdegreevalue += (miyuan + i)->fitdegreevalue;
}
for (int i = 0; i < SN; i++)
{
(miyuan + i)->selectprobability = (miyuan + i)->fitdegreevalue / sumfitdegreevalue;
}
}
void OnLookerBeeOperate()//观察蜂操作
{
std::uniform_int_distribution<int> uD(1, Dimension); //随机数分布对象
std::uniform_int_distribution<int> uSN(1, SN); //随机数分布对象
int m = 0;
while (m < SN)//为所有的观察蜂按照概率选择蜜源并搜索新蜜源,计算新蜜源适应值
{
double m_choosedprobability = u(random);//0~1之间的随机数
for (int i = 0; i < SN; i++)
{
if (m_choosedprobability < (miyuan + i)->selectprobability)
{
int k, jie;//随机生成且 k≠i k∈[1,SN]
jie = uD(random) - 1;//jie为【1,Dimension】上的随机数
double φ = u1(random);//φ表示[-1,1]之间的随机数
while (true)
{
k = uSN(random) - 1;
if (k != i)break;
}
for (int j = 0; j < Dimension; j++)
(onlookerbee + m)->x[j] = (miyuan + i)->x[j];
(onlookerbee + m)->x[jie] = (miyuan + i)->x[jie] + φ*((miyuan + i)->x[jie] - (miyuan + k)->x[jie]);//搜索新蜜源
if ((onlookerbee + m)->x[jie] > xmax) (onlookerbee + m)->x[jie] = xmax;
else if ((onlookerbee + m)->x[jie] < xmin) (onlookerbee + m)->x[jie] = xmin;//判断是否越界
Adjuxt_validParticle((onlookerbee + m)->x);//对蜜源路径进行有效性调整,确保是TSP问题的一个可行解
(onlookerbee + m)->fitdegreevalue = CalculateFitDegree(CalculateFitValue(*(onlookerbee + m)));
//贪心策略选择蜜源
if (CalculateFitValue(*(onlookerbee + m)) < CalculateFitValue(*(miyuan + i)))
{
for (int j = 0; j < Dimension; j++)
(miyuan + i)->x[j] = (onlookerbee + m)->x[j];
(miyuan + i)->fitdegreevalue = (onlookerbee + m)->fitdegreevalue;
}
else
(miyuan + i)->limitcishu++;
m++;
}break;
}
}
}
void ScoutBeeOperate()//侦查蜂操作,决定蜜源是否放弃,并随机产生新位置替代原蜜源
{
for (int i = 0; i < SN; i++)
{
if ((miyuan + i)->limitcishu >= Limit)
{
for (int j = 0; j < Dimension; j++)
{
(miyuan + i)->x[j] = round(xmin + u(random)*(xmax - xmin));//随机初始化可行解;//随机产生可行解
}
Adjuxt_validParticle((miyuan + i)->x);
(miyuan + i)->limitcishu = 0;
(miyuan + i)->fitdegreevalue = CalculateFitDegree(CalculateFitValue(*(miyuan + i)));
}
}
}
void SaveBestMiyuan()//记录最优解的函数
{
for (int i = 0; i < SN; i++)
{
if (CalculateFitValue(*(miyuan + i)) < CalculateFitValue(bestmiyuan))
{
for (int j = 0; j < Dimension; j++)
bestmiyuan.x[j] = (miyuan + i)->x[j];
}
}
}
void shuchumiyuan()
{
for (int i = 0; i < SN; i++)
{
std::cout << "蜜源" << i + 1<<"->";
for (int j = 0; j < Dimension; j++)
{
if (j == Dimension - 1)std::cout << (miyuan + i)->x[j] <<")对应的距离为: "<<CalculateFitValue(*(miyuan+i))<< endl;
else if(j==0)
std::cout <<"("<< (miyuan + i)->x[j] << ", ";
else
std::cout << (miyuan + i)->x[j] << ", ";
}
}
}
void ShuchuBestmiyuan()
{
for (int j = 0; j < Dimension; j++)
{
if (j == Dimension - 1) std::cout << bestmiyuan.x[j] << ")" << "对应的距离为:" << CalculateFitValue(bestmiyuan) << endl;
else if (j == 0) std::cout << "(" << bestmiyuan.x[j] << ",";
else std::cout << bestmiyuan.x[j] << ",";
}
}
void DoABC(int sn, int dimension, int mcn, int limit,string filename)//运行人工蜂群算法的函数
{
ofstream outfile;
outfile.open("result.txt", ios::trunc);
Map_City.Readcoordinatetxt(filename);
Map_City.shuchu();
outfile << "城市名称 " << "坐标x" << " " << "坐标y" << endl;
for (int i = 0; i < citycount; i++)
outfile << Map_City.city[i].name << " " << Map_City.city[i].x << " " << Map_City.city[i].y << endl;
outfile << "距离矩阵: " << endl;
for (int i = 0; i < citycount; i++)
{
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << Map_City.distance[i][j] << endl;
else
outfile << Map_City.distance[i][j] << " ";
}
}
Init(sn, dimension, mcn, limit);//初始化
shuchumiyuan();
outfile << "初始化后的蜜源如下:" << endl;
for (int i = 0; i < SN; i++)
{
outfile << "蜜源" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (miyuan + i)->x[j] << ") = " << CalculateFitValue(*(miyuan + i)) << endl;
else if (j == 0)
outfile << "f(" << (miyuan + i)->x[j] << ",";
else
outfile << (miyuan + i)->x[j] << ",";
}
}
SaveBestMiyuan();//保存最好蜜源
ShuchuBestmiyuan();
for (int k = 0; k < MCN; k++)
{
EmployedBeeOperate();
CalculateProbability();
OnLookerBeeOperate();
SaveBestMiyuan();
ScoutBeeOperate();
SaveBestMiyuan();
std::cout << "第" << k + 1 << "次迭代的最优解为:";
ShuchuBestmiyuan();
outfile << "第"<<k+1<<"次迭代后的蜜源如下:" << endl;
for (int i = 0; i < SN; i++)
{
outfile << "蜜源" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (miyuan + i)->x[j] << ") = " << CalculateFitValue(*(miyuan + i)) << endl;
else if (j == 0)
outfile << "f(" << (miyuan + i)->x[j] << ",";
else
outfile << (miyuan + i)->x[j] << ",";
}
}
outfile << "第" << k + 1 << "次迭代的最优蜜源为:";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << bestmiyuan.x[j] << ") = " << CalculateFitValue(bestmiyuan) << endl;
else if (j == 0)
outfile << "f(" << bestmiyuan.x[j] << ",";
else
outfile << bestmiyuan.x[j] << ",";
}
}
outfile.close();
}
};
int main()
{
system("mode con cols=200");
system("color fc");
std::cout << "人工蜂群算法求解TSP旅行商问题!" << endl;
ABC abc;
abc.DoABC(50, citycount, 200, 20, "E:\\计算智能代码\\ABC_TSP\\ABC_TSP\\bayg29.tsp");
system("pause");
return 0;
}