AFA算法求解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 <fstream>
#include <string>
#include <random>
#include <time.h>
using namespace std;
3、所需的类
所需的类包括城市类City、包含城市的地图类Graph、人工鱼类AF、人工鱼群算法类AFA。
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 人工鱼类AF
class AF
{
public:
int dimension;//个体变量维数
int *x;
void Init(int Dim)//初始化函数
{
dimension = Dim;
x = new int[dimension];
x = Random_N(dimension);
}
double fitfunctionvalue()//个体适应值计算函数,即计算路径对应的距离
{
double fitvalue = 0;
for (int j = 0; j < dimension - 1; j++)
fitvalue += Map_City.distance[*(x + j) - 1][*(x + j + 1) - 1];
fitvalue += Map_City.distance[*(x + dimension - 1) - 1][*x - 1];
return fitvalue;
}
void shuchu()
{
for (int j = 0; j < dimension; j++)
{
if(j==0)
std::cout <<"f("<< x[j] << ",";
else if(j==dimension-1)
std::cout<< x[j] << ") =";
else
std::cout<<x[j] << ",";
}
std::cout <<fitfunctionvalue()<< endl;
}
};
3.4 人工鱼群算法类AFA
class AFA
{
public:
int N;//种群规模
int Dimension;//维数
double step = 0;
double visual = 0;
double try_number = 0;
double delta = 0;
AF *af;
AF Bestfish;//公告板最优解
void Init(int num, int Dim, double Step, double Visual, double Try_number, double Delta)//初始化函数
{
N = num;
Dimension = Dim;
step = Step;
visual = Visual;
try_number = Try_number;
delta = Delta;
af = new AF[N];
for (int i = 0; i < N; i++)
(af + i)->Init(Dimension);
Bestfish.Init(Dimension);
double bestfitness = af->fitfunctionvalue();
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = af->x[j];
for (int i = 0; i < N; i++)
{
if ((af + i)->fitfunctionvalue() < bestfitness)
{
bestfitness = (af + i)->fitfunctionvalue();
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = (af + i)->x[j];
}
}
}
double Distance(AF af1, AF af2)//计算两条鱼距离的函数
{
double dist = 0;
for (int i = 0; i < Dimension; i++)
dist += pow(af1.x[i] - af2.x[i], 2.0);
dist = sqrt(dist / float(Dimension));
return dist;
}
void prey(int id)//觅食行为
{
AF AFNew;
AFNew.Init(Dimension);
for (int i = 0; i < try_number; i++)
{
for (int j = 0; j < Dimension; j++)
AFNew.x[j] = (af + id)->x[j] + r(random) * visual;
double Yi = 0, Yj = 0;
Yi = (af + id)->fitfunctionvalue();
Yj = AFNew.fitfunctionvalue();
if (Yi > Yj)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = round((af + id)->x[j] + r(random)*step*(AFNew.x[j] - (af + id)->x[j]) / Distance(AFNew, *(af + id)));
}
else
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = round((af + id)->x[j] + r(random)*step);
}
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
}
void swarm(int id)//聚群行为
{
AF AFXc;
AFXc.Init(Dimension);
for (int j = 0; j < Dimension; j++) AFXc.x[j] = 0;
double nf = 0;
for (int i = 0; i < N; i++)
if ((Distance(*(af + id), *(af + i)) < visual) && (Distance(*(af + id), *(af + i)) != 0))
{
nf++;
for (int j = 0; j < Dimension; j++)
AFXc.x[j] += (af + i)->x[j];
}
for (int j = 0; j < Dimension; j++)
AFXc.x[j] = AFXc.x[j] / nf;//计算邻域伙伴的中心位置
double Yc = AFXc.fitfunctionvalue(), Yi = (af + id)->fitfunctionvalue();
if (Yc / nf < delta*Yi)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = (af + id)->x[j] + r(random)*step*(AFXc.x[j] - (af + id)->x[j]) / Distance(AFXc, *(af + id));
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
else
prey(id);
}
void follow(int id)//追尾行为
{
double Ymin = INFINITY;
AF AFXmin;
AFXmin.Init(Dimension);
for (int j = 0; j < Dimension; j++) AFXmin.x[j] = 0;
for (int i = 0; i < N; i++)
{
double dij = Distance(*(af + id), *(af + i)), Yj = (af + i)->fitfunctionvalue();
if (dij != 0 && dij<visual && Yj <Ymin)
{
Ymin = Yj;
for (int j = 0; j < Dimension; j++)
AFXmin.x[j] = (af + i)->x[j];
}
}
double nf = 0;
for (int i = 0; i < N; i++)
{
double dminj = Distance(AFXmin, *(af + i));
if (dminj != 0 && dminj < visual)
nf++;
}
double Yi = (af + id)->fitfunctionvalue();
if (Ymin / nf < delta *Yi)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = (af + id)->x[j] + r(random)*step*(AFXmin.x[j] - (af + id)->x[j]) / Distance(AFXmin, *(af + id));
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
else
prey(id);
}
void evaluate(int id)
{
if ((af + id)->fitfunctionvalue() < Bestfish.fitfunctionvalue())
{
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = (af + id)->x[j];
}
}
void DoAFA(int num, int Dim, double Step, double Visual, double Try_number, double Delta, int Itetime,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(num, Dim, Step, Visual, Try_number, Delta);
Shuchu();
outfile << "初始化后的鱼群如下:" << endl;
for (int i = 0; i < N; i++)
{
outfile << "鱼" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (af + i)->x[j] << ") = " << (af+i)->fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << (af + i)->x[j] << ",";
else
outfile << (af + i)->x[j] << ",";
}
}
outfile << "初始化后的最佳鱼为:";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << Bestfish.x[j] << ") = " << Bestfish.fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << Bestfish.x[j] << ",";
else
outfile << Bestfish.x[j] << ",";
}
for (int t = 0; t < Itetime; t++)
{
for (int i = 0; i < N; i++)
{
prey(i);
swarm(i);
follow(i);
evaluate(i);
}
std::cout << "第" << t + 1 << "次迭代最优位置为Bestfish:";
Bestfish.shuchu();
outfile << "第" << t + 1 << "次迭代后的鱼群如下:" << endl;
for (int i = 0; i < N; i++)
{
outfile << "鱼" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (af + i)->x[j] << ") = " << (af + i)->fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << (af + i)->x[j] << ",";
else
outfile << (af + i)->x[j] << ",";
}
}
outfile << "第" << t + 1 << "次迭代后的最优位置如下:" << endl;
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << Bestfish.x[j] << ") = " << Bestfish.fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << Bestfish.x[j] << ",";
else
outfile << Bestfish.x[j] << ",";
}
}
std::cout << "迭代结束后最优位置为Bestfish:";
Bestfish.shuchu();
}
void Shuchu()
{
for (int i = 0; i < N; i++)
{
std::cout << "第" << i + 1 << "条鱼: ";
(af + i)->shuchu();
}
}
};
4、自定义函数
自定义函数包括:四舍五入取整函数、路径随机初始化函数、调整鱼群路径有效性的函数。
4.1 四舍五入取整函数
double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
4.2 路径随机初始化函数
int * Random_N(int n)//随机生成TSP问题的一个可行解的函数
{
int *geti;
geti = new int[n];
int j = 0;
while (j<n)
{
while (true)
{
int flag = -1;
int temp = rand() % n + 1;
if (j > 0)
{
int k = 0;
for (; k < j; k++)
{
if (temp == *(geti + k))break;
}
if (k == j)
{
*(geti + j) = temp;
flag = 1;
}
}
else
{
*(geti + j) = temp;
flag = 1;
}
if (flag == 1)break;
}
j++;
}
return geti;
}
4.3 调整路径有效性的函数
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;
int Xmax = citycount, Xmin = 1;//变量的可行域
std::default_random_engine random((unsigned int)time(NULL));
std::uniform_real_distribution<double> u(Xmin, Xmax); //随机数分布对象
std::uniform_real_distribution<double> r(0, 1); //随机数分布对象
Graph Map_City;//定义全局对象图,放在Graph类后
6、主函数
int main()
{
system("mode con cols=200");
system("color fc");
std::cout << "人工鱼群算法求解TSP旅行商问题!" << endl;
AFA yq;
while (true)
{
int num = 0;
std::cout << "请输入迭代的次数:";
cin >> num;
if (num == 0)break;
else yq.DoAFA(20, 29, 2, 100, 10, 0.618, num, "E:\\计算智能代码\\AFA_TSP\\AFA_TSP\\bayg29.tsp");
}
system("pause");
return 0;
}
7、运行结果
7.1控制台运行结果
7.2 生成的result.txt文件结果
8、MATLAB绘制最优路径结果
附录(完整代码)
#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <time.h>
using namespace std;
const int citycount = 29;
int Xmax = citycount, Xmin = 1;//变量的可行域
std::default_random_engine random((unsigned int)time(NULL));
std::uniform_real_distribution<double> u(Xmin, Xmax); //随机数分布对象
std::uniform_real_distribution<double> r(0, 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;
}
}
}
int * Random_N(int n)//随机生成TSP问题的一个可行解的函数
{
int *geti;
geti = new int[n];
int j = 0;
while (j<n)
{
while (true)
{
int flag = -1;
int temp = rand() % n + 1;
if (j > 0)
{
int k = 0;
for (; k < j; k++)
{
if (temp == *(geti + k))break;
}
if (k == j)
{
*(geti + j) = temp;
flag = 1;
}
}
else
{
*(geti + j) = temp;
flag = 1;
}
if (flag == 1)break;
}
j++;
}
return geti;
}
class AF
{
public:
int dimension;//个体变量维数
int *x;
void Init(int Dim)//初始化函数
{
dimension = Dim;
x = new int[dimension];
x = Random_N(dimension);
}
double fitfunctionvalue()//个体适应值计算函数,即计算路径对应的距离
{
double fitvalue = 0;
for (int j = 0; j < dimension - 1; j++)
fitvalue += Map_City.distance[*(x + j) - 1][*(x + j + 1) - 1];
fitvalue += Map_City.distance[*(x + dimension - 1) - 1][*x - 1];
return fitvalue;
}
void shuchu()
{
for (int j = 0; j < dimension; j++)
{
if(j==0)
std::cout <<"f("<< x[j] << ",";
else if(j==dimension-1)
std::cout<< x[j] << ") =";
else
std::cout<<x[j] << ",";
}
std::cout <<fitfunctionvalue()<< endl;
}
};
class AFA
{
public:
int N;//种群规模
int Dimension;//维数
double step = 0;
double visual = 0;
double try_number = 0;
double delta = 0;
AF *af;
AF Bestfish;//公告板最优解
void Init(int num, int Dim, double Step, double Visual, double Try_number, double Delta)//初始化函数
{
N = num;
Dimension = Dim;
step = Step;
visual = Visual;
try_number = Try_number;
delta = Delta;
af = new AF[N];
for (int i = 0; i < N; i++)
(af + i)->Init(Dimension);
Bestfish.Init(Dimension);
double bestfitness = af->fitfunctionvalue();
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = af->x[j];
for (int i = 0; i < N; i++)
{
if ((af + i)->fitfunctionvalue() < bestfitness)
{
bestfitness = (af + i)->fitfunctionvalue();
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = (af + i)->x[j];
}
}
}
double Distance(AF af1, AF af2)//计算两条鱼距离的函数
{
double dist = 0;
for (int i = 0; i < Dimension; i++)
dist += pow(af1.x[i] - af2.x[i], 2.0);
dist = sqrt(dist / float(Dimension));
return dist;
}
void prey(int id)//觅食行为
{
AF AFNew;
AFNew.Init(Dimension);
for (int i = 0; i < try_number; i++)
{
for (int j = 0; j < Dimension; j++)
AFNew.x[j] = (af + id)->x[j] + r(random) * visual;
double Yi = 0, Yj = 0;
Yi = (af + id)->fitfunctionvalue();
Yj = AFNew.fitfunctionvalue();
if (Yi > Yj)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = round((af + id)->x[j] + r(random)*step*(AFNew.x[j] - (af + id)->x[j]) / Distance(AFNew, *(af + id)));
}
else
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = round((af + id)->x[j] + r(random)*step);
}
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
}
void swarm(int id)//聚群行为
{
AF AFXc;
AFXc.Init(Dimension);
for (int j = 0; j < Dimension; j++) AFXc.x[j] = 0;
double nf = 0;
for (int i = 0; i < N; i++)
if ((Distance(*(af + id), *(af + i)) < visual) && (Distance(*(af + id), *(af + i)) != 0))
{
nf++;
for (int j = 0; j < Dimension; j++)
AFXc.x[j] += (af + i)->x[j];
}
for (int j = 0; j < Dimension; j++)
AFXc.x[j] = AFXc.x[j] / nf;//计算邻域伙伴的中心位置
double Yc = AFXc.fitfunctionvalue(), Yi = (af + id)->fitfunctionvalue();
if (Yc / nf < delta*Yi)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = (af + id)->x[j] + r(random)*step*(AFXc.x[j] - (af + id)->x[j]) / Distance(AFXc, *(af + id));
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
else
prey(id);
}
void follow(int id)//追尾行为
{
double Ymin = INFINITY;
AF AFXmin;
AFXmin.Init(Dimension);
for (int j = 0; j < Dimension; j++) AFXmin.x[j] = 0;
for (int i = 0; i < N; i++)
{
double dij = Distance(*(af + id), *(af + i)), Yj = (af + i)->fitfunctionvalue();
if (dij != 0 && dij<visual && Yj <Ymin)
{
Ymin = Yj;
for (int j = 0; j < Dimension; j++)
AFXmin.x[j] = (af + i)->x[j];
}
}
double nf = 0;
for (int i = 0; i < N; i++)
{
double dminj = Distance(AFXmin, *(af + i));
if (dminj != 0 && dminj < visual)
nf++;
}
double Yi = (af + id)->fitfunctionvalue();
if (Ymin / nf < delta *Yi)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = (af + id)->x[j] + r(random)*step*(AFXmin.x[j] - (af + id)->x[j]) / Distance(AFXmin, *(af + id));
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
else
prey(id);
}
void evaluate(int id)
{
if ((af + id)->fitfunctionvalue() < Bestfish.fitfunctionvalue())
{
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = (af + id)->x[j];
}
}
void DoAFA(int num, int Dim, double Step, double Visual, double Try_number, double Delta, int Itetime,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(num, Dim, Step, Visual, Try_number, Delta);
Shuchu();
outfile << "初始化后的鱼群如下:" << endl;
for (int i = 0; i < N; i++)
{
outfile << "鱼" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (af + i)->x[j] << ") = " << (af+i)->fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << (af + i)->x[j] << ",";
else
outfile << (af + i)->x[j] << ",";
}
}
outfile << "初始化后的最佳鱼为:";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << Bestfish.x[j] << ") = " << Bestfish.fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << Bestfish.x[j] << ",";
else
outfile << Bestfish.x[j] << ",";
}
for (int t = 0; t < Itetime; t++)
{
for (int i = 0; i < N; i++)
{
prey(i);
swarm(i);
follow(i);
evaluate(i);
}
std::cout << "第" << t + 1 << "次迭代最优位置为Bestfish:";
Bestfish.shuchu();
outfile << "第" << t + 1 << "次迭代后的鱼群如下:" << endl;
for (int i = 0; i < N; i++)
{
outfile << "鱼" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (af + i)->x[j] << ") = " << (af + i)->fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << (af + i)->x[j] << ",";
else
outfile << (af + i)->x[j] << ",";
}
}
outfile << "第" << t + 1 << "次迭代后的最优位置如下:" << endl;
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << Bestfish.x[j] << ") = " << Bestfish.fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << Bestfish.x[j] << ",";
else
outfile << Bestfish.x[j] << ",";
}
}
std::cout << "迭代结束后最优位置为Bestfish:";
Bestfish.shuchu();
}
void Shuchu()
{
for (int i = 0; i < N; i++)
{
std::cout << "第" << i + 1 << "条鱼: ";
(af + i)->shuchu();
}
}
};
int main()
{
system("mode con cols=200");
system("color fc");
std::cout << "人工鱼群算法求解TSP旅行商问题!" << endl;
AFA yq;
while (true)
{
int num = 0;
std::cout << "请输入迭代的次数:";
cin >> num;
if (num == 0)break;
else yq.DoAFA(20, 29, 2, 100, 10, 0.618, num, "E:\\计算智能代码\\AFA_TSP\\AFA_TSP\\bayg29.tsp");
}
system("pause");
return 0;
}
附录2(目前可运行的完整代码 注释372行 prey(i);)
#include <iostream>
#include <fstream>
#include <string>
#include <random>
#include <time.h>
using namespace std;
const int citycount = 29;
int Xmax = citycount, Xmin = 1;//变量的可行域
std::default_random_engine random((unsigned int)time(NULL));
std::uniform_real_distribution<double> u(Xmin, Xmax); //随机数分布对象
std::uniform_real_distribution<double> r(0, 1); //随机数分布对象
double round_self(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
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(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_self(distance[i][j] < distance[i][j]))distance[i][j] = round_self(distance[i][j]) + 1;
else distance[i][j] = round_self(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类后
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;
}
}
}
int* Random_N(int n)//随机生成TSP问题的一个可行解的函数
{
int* geti;
geti = new int[n];
int j = 0;
while (j < n)
{
while (true)
{
int flag = -1;
int temp = rand() % n + 1;
if (j > 0)
{
int k = 0;
for (; k < j; k++)
{
if (temp == *(geti + k))break;
}
if (k == j)
{
*(geti + j) = temp;
flag = 1;
}
}
else
{
*(geti + j) = temp;
flag = 1;
}
if (flag == 1)break;
}
j++;
}
return geti;
}
class AF
{
public:
int dimension;//个体变量维数
int* x;
void Init(int Dim)//初始化函数
{
dimension = Dim;
x = new int[dimension];
x = Random_N(dimension);
}
double fitfunctionvalue()//个体适应值计算函数,即计算路径对应的距离
{
double fitvalue = 0;
for (int j = 0; j < dimension - 1; j++)
fitvalue += Map_City.distance[*(x + j) - 1][*(x + j + 1) - 1];
fitvalue += Map_City.distance[*(x + dimension - 1) - 1][*x - 1];
return fitvalue;
}
void shuchu()
{
for (int j = 0; j < dimension; j++)
{
if (j == 0)
std::cout << "f(" << x[j] << ",";
else if (j == dimension - 1)
std::cout << x[j] << ") =";
else
std::cout << x[j] << ",";
}
std::cout << fitfunctionvalue() << endl;
}
};
class AFA
{
public:
int N;//种群规模
int Dimension;//维数
double step = 0;
double visual = 0;
double try_number = 0;
double delta = 0;
AF* af;
AF Bestfish;//公告板最优解
void Init(int num, int Dim, double Step, double Visual, double Try_number, double Delta)//初始化函数
{
N = num;
Dimension = Dim;
step = Step;
visual = Visual;
try_number = Try_number;
delta = Delta;
af = new AF[N];
for (int i = 0; i < N; i++)
(af + i)->Init(Dimension);
Bestfish.Init(Dimension);
double bestfitness = af->fitfunctionvalue();
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = af->x[j];
for (int i = 0; i < N; i++)
{
if ((af + i)->fitfunctionvalue() < bestfitness)
{
bestfitness = (af + i)->fitfunctionvalue();
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = (af + i)->x[j];
}
}
}
double Distance(AF af1, AF af2)//计算两条鱼距离的函数
{
double dist = 0;
for (int i = 0; i < Dimension; i++)
dist += pow(af1.x[i] - af2.x[i], 2.0);
dist = sqrt(dist / float(Dimension));
return dist;
}
void prey(int id)//觅食行为
{
AF AFNew;
AFNew.Init(Dimension);
for (int i = 0; i < try_number; i++)
{
for (int j = 0; j < Dimension; j++)
AFNew.x[j] = (af + id)->x[j] + r(random) * visual;
double Yi = 0, Yj = 0;
Yi = (af + id)->fitfunctionvalue();
Yj = AFNew.fitfunctionvalue();
if (Yi > Yj)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = round_self((af + id)->x[j] + r(random) * step * (AFNew.x[j] - (af + id)->x[j]) / Distance(AFNew, *(af + id)));
}
else
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = round_self((af + id)->x[j] + r(random) * step);
}
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
}
void swarm(int id)//聚群行为
{
AF AFXc;
AFXc.Init(Dimension);
for (int j = 0; j < Dimension; j++) AFXc.x[j] = 0;
double nf = 0;
for (int i = 0; i < N; i++)
if ((Distance(*(af + id), *(af + i)) < visual) && (Distance(*(af + id), *(af + i)) != 0))
{
nf++;
for (int j = 0; j < Dimension; j++)
AFXc.x[j] += (af + i)->x[j];
}
for (int j = 0; j < Dimension; j++)
AFXc.x[j] = AFXc.x[j] / nf;//计算邻域伙伴的中心位置
double Yc = AFXc.fitfunctionvalue(), Yi = (af + id)->fitfunctionvalue();
if (Yc / nf < delta * Yi)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = (af + id)->x[j] + r(random) * step * (AFXc.x[j] - (af + id)->x[j]) / Distance(AFXc, *(af + id));
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
else
prey(id);
}
void follow(int id)//追尾行为
{
double Ymin = INFINITY;
AF AFXmin;
AFXmin.Init(Dimension);
for (int j = 0; j < Dimension; j++) AFXmin.x[j] = 0;
for (int i = 0; i < N; i++)
{
double dij = Distance(*(af + id), *(af + i)), Yj = (af + i)->fitfunctionvalue();
if (dij != 0 && dij < visual && Yj < Ymin)
{
Ymin = Yj;
for (int j = 0; j < Dimension; j++)
AFXmin.x[j] = (af + i)->x[j];
}
}
double nf = 0;
for (int i = 0; i < N; i++)
{
double dminj = Distance(AFXmin, *(af + i));
if (dminj != 0 && dminj < visual)
nf++;
}
double Yi = (af + id)->fitfunctionvalue();
if (Ymin / nf < delta * Yi)
{
for (int j = 0; j < Dimension; j++)
(af + id)->x[j] = (af + id)->x[j] + r(random) * step * (AFXmin.x[j] - (af + id)->x[j]) / Distance(AFXmin, *(af + id));
Adjuxt_validParticle((af + id)->x);//对个体进行有效性调整,使之符合TSP问题的一个可行有效解
}
else
prey(id);
}
void evaluate(int id)
{
if ((af + id)->fitfunctionvalue() < Bestfish.fitfunctionvalue())
{
for (int j = 0; j < Dimension; j++)
Bestfish.x[j] = (af + id)->x[j];
}
}
void DoAFA(int num, int Dim, double Step, double Visual, double Try_number, double Delta, int Itetime, 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(num, Dim, Step, Visual, Try_number, Delta);
Shuchu();
outfile << "初始化后的鱼群如下:" << endl;
for (int i = 0; i < N; i++)
{
outfile << "鱼" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (af + i)->x[j] << ") = " << (af + i)->fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << (af + i)->x[j] << ",";
else
outfile << (af + i)->x[j] << ",";
}
}
outfile << "初始化后的最佳鱼为:";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << Bestfish.x[j] << ") = " << Bestfish.fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << Bestfish.x[j] << ",";
else
outfile << Bestfish.x[j] << ",";
}
for (int t = 0; t < Itetime; t++)
{
for (int i = 0; i < N; i++)
{
//prey(i);
swarm(i);
follow(i);
evaluate(i);
}
std::cout << "第" << t + 1 << "次迭代最优位置为Bestfish:";
Bestfish.shuchu();
outfile << "第" << t + 1 << "次迭代后的鱼群如下:" << endl;
for (int i = 0; i < N; i++)
{
outfile << "鱼" << i + 1 << "->";
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << (af + i)->x[j] << ") = " << (af + i)->fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << (af + i)->x[j] << ",";
else
outfile << (af + i)->x[j] << ",";
}
}
outfile << "第" << t + 1 << "次迭代后的最优位置如下:" << endl;
for (int j = 0; j < citycount; j++)
{
if (j == citycount - 1)
outfile << Bestfish.x[j] << ") = " << Bestfish.fitfunctionvalue() << endl;
else if (j == 0)
outfile << "f(" << Bestfish.x[j] << ",";
else
outfile << Bestfish.x[j] << ",";
}
}
std::cout << "迭代结束后最优位置为Bestfish:";
Bestfish.shuchu();
}
void Shuchu()
{
for (int i = 0; i < N; i++)
{
std::cout << "第" << i + 1 << "条鱼: ";
(af + i)->shuchu();
}
}
};
int main()
{
system("mode con cols=200");
system("color fc");
std::cout << "人工鱼群算法求解TSP旅行商问题!" << endl;
AFA yq;
while (true)
{
int num = 0;
std::cout << "请输入迭代的次数:";
cin >> num;
if (num == 0)break;
else yq.DoAFA(20, 29, 2, 100, 10, 0.618, num, "bayg29.tsp");
}
system("pause");
return 0;
}