1.N>=8。
2.随即生成N个城市间的连接矩阵。
3.指定起始城市。
4.给出每一代的最优路线和总路线长度。
5.以代数T作为结束条件,T>=50。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int city_num = 8; //城市数量
const int unit_num = 100; //群体规模
double ps = 0.01; //变异概率
const int genmax = 50; //最大迭代数
//城市间距离矩阵
int length_table[city_num][city_num] = {
{
0, 2, 3, 4, 5, 7, 3, 1},
{
2, 0, 2, 6, 3, 5, 4, 2},
{
3, 2, 0, 1, 9, 8, 7, 6},
{
4, 6, 1, 0, 5, 4, 3, 2},
{
5, 3, 9, 5, 0, 2, 1, 6},
{
7, 5, 8, 4, 2 ,0, 3, 6},
{
3, 4, 7, 3, 1, 3, 0, 5},
{
1, 2, 6, 2, 6, 6, 5, 0}
};
class Unit {
public:
int path[city_num+1]; //个体路径信息
int length; //个体代价
};
bool cmp(Unit u1, Unit u2) {
return u1.length < u2.length; }
bool IsEqual(Unit u1, Unit u2) {
for (int j = 0; j < city_num; j++)
if (u1.path[j] != u2.path[j])
return false;
return true;
}
bool IsExist(vector<Unit> temp, Unit u) {
for (int i = 0; i < temp.size(); i++)
if(IsEqual(temp[i],u))
return true;
return false;
}
void PrintPath(Unit u) {
for (int j = 0; j <= city_num; j++)
printf("%d ", u.path[j]);
}
class Group {
public:
Group();
Unit group[unit_num];
Unit best;
double alllength;
int best_gen;
void assess();//对每个个体进行评估
void choose_copy();
int sort_group();
void cross(Unit &father, Unit &mother);//交叉
void mutation(Unit &t);//突变
void print();//输出信息
void work();//种群进化
private:
};
Group::Group() {
//随机产生N个染色体组成每个种群
best.length = 0x3f3f3f3f;
best_gen = 0;
int start_city;
cout << "Please input the start city, and it should be in a range of 0~" << city_num - 1<<" : ";
cin >> start_city;
for (int i = 0; i < unit_num; i++) {
group[i].path[0]=start_city;
bool flag[city_num] = {
};
flag[start_city]=true;
for (int j = 1; j < city_num; j++) {
int t_city = rand() % city_num;
while (flag[t_city])
t_city = rand() % city_num;
flag[t_city] = true;
group[i].path[j] = t_city;
}
group[i].path[city_num] = group[i].path[0];
}
}
void Group::assess() {
//计算每个个体的适应度的倒数
alllength = 0;
for (int k = 0; k < unit_num; k++) {
group[k].length = 0;
for (int i = 0; i < city_num; i++)
group[k].length += length_table[group[k].path[i]][group[k].path[i+1]];
alllength += 1.0/group[k].length;
}
//cout << "alllength: " << alllength << endl;
}
int Group::sort_group(){
Unit *u = group;
sort(u, u + unit_num, cmp); //根据评估结果排序
return u->length;
}
void Group::choose_copy(){
//选择-复制
for (int i = 0; i < unit_num;i++){
double m = 0;
double p;
double r = (double)rand()/RAND_MAX; //r为0至1的随机数
for (int j = 0; j < unit_num; j++) {
p = 1.0 / (group[j].length * alllength);
m = m + p;
if (r <= m){
for (int t = 0; t <= city_num;t++)
group[i].path[t] = group[j].path[t];
group[i].length = group[j].length;
//printf("第%d个个体选择的是%d\n", i+1, j+1);
break;
}
}
}
}
void Group::cross(Unit &father, Unit &mother) __attribute__ ((__MINGW_ATTRIB_NO_OPTIMIZE)) {
//交叉
bool flag1[city_num] = {
};
bool flag2[city_num] = {
};
int l = 1 + (rand() % (city_num - 1));
int r = 1 + (rand() % (city_num - 1));
if (l > r)
swap(l, r);
Unit son1, son2;
for (int i = l; i <= r; i++){
son1.path[i] = father.path[i];
flag1[father.path[i]]=true;
son2.path[i] = mother.path[i];
flag2[mother.path[i]]=true;
}
for (int i = 0; i < l; i++) {
//找到l~r中映射的城市,并在子种群中确定城市
if(!flag1[mother.path[i]])
son1.path[i] = mother.path[i];
else {
int temp = mother.path[i];
int j;
while (flag1[temp]) {
for (j = l; j <= r; j++)
if (father.path[j] == temp)
break;
temp=mother.path[j];
}
son1.path[i]=temp;
}
if(!flag2[father.path[i]])
son2.path[i] = father.path[i];
else {
int temp = father.path[i];
int j;
while (flag2[temp]) {
for (j = l; j <= r; j++)
if (mother.path[j] == temp)
break;
temp=father.path[j];
}
son2.path[i]=temp;
}
}
for (int i = r + 1; i <= city_num; i++){
//找到l~r中映射的城市,并在子种群中确定城市
if(!flag1[mother.path[i]])
son1.path[i] = mother.path[i];
else {
int temp = mother.path[i];
int j;
while (flag1[temp]) {
for (j = l; j <= r; j++)
if (father.path[j] == temp)
break;
temp=mother.path[j];
}
son1.path[i]=temp;
}
if(!flag2[father.path[i]])
son2.path[i] = father.path[i];
else {
int temp = father.path[i];
int j;
while (flag2[temp]) {
for (j = l; j <= r; j++)
if (mother.path[j] == temp)
break;
temp=father.path[j];
}
son2.path[i]=temp;
}
}
for (int i = 0; i <= city_num;i++){
mother.path[i] = son1.path[i];
father.path[i] = son2.path[i];
}
}
void Group::mutation(Unit &t) {
//变异
int one = 1 + (rand() % (city_num - 1));
int two = 1 + (rand() % (city_num - 1));
while (two == one)
two = rand() % city_num;
swap(t.path[one], t.path[two]);
}
void Group::print(){
for (int i = 0; i < unit_num; i++){
printf("第%d个个体,路径信息为", i+1);
PrintPath(group[i]);
printf(";总权值:%d;\n", group[i].length);
}
printf("最优个体,路径信息为:\n");
vector<Unit> temp;
int length=sort_group();
for (int i = 0; i < unit_num; i++) {
if(group[i].length==length &&(!IsExist(temp, group[i]))){
PrintPath(group[i]);
cout << endl;
temp.push_back(group[i]);
}
}
printf("总权值:%d;\n", length);
temp.clear();
}
void Group::work() {
//遗传算法
for (int i = 0; i < genmax; i++) {
assess(); //评估
if(i+1<=2||(i+1)%10==0){
printf("第%d代:\n", i + 1);
print();
}
if (best.length > group[0].length) {
//
memcpy(&best, &group[0], sizeof(group[0]));
best_gen = i+1;
}
choose_copy();//选择复制
for (int j = 0; j + 1 < unit_num; j += 2)//交叉
cross(group[j], group[j + 1]);
for (int j = 0; j < unit_num; j++){
//变异
int temp = rand() % 100;
if(temp==j)
mutation(group[j]);
}
}
}
Unit group[unit_num]; //种群变量
Unit bestone; //记录最短路径
int generation_num; //记录当前达到了第几代
int main() {
srand((int)time(0));
Group g;
g.work();
printf("求解结果路径信息为:");
PrintPath(g.best);
printf("; 总权值:%d; 第%d代;\n", g.best.length, g.best_gen);
return 0;
}