c语言设计遗传算法旅行商,C语言编写遗传算法解决TSP旅行商问题

#include #define RAND(X) (rand()%(X))

#define NUM_CITY(30)

#define GENERATIONS(5000)

#define MAX_SIZE(50)

#define LOWEST_ALIVE(1.0/MAX_SIZE)

typedef struct _Group{

int city[NUM_CITY];

int adapt;

float pAlive;

}Group;

int cityDistance[NUM_CITY][NUM_CITY];

Group g_Group[MAX_SIZE];

floatPm = 0.1;

floatPc = 0.8;

int bestOne;

void getFitness(Group &group) // 得到适应值

{

int distance = 0;

int temp;

int x1, x2, y1, y2;

int tdistance;

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

{

distance += cityDistance[group.city[i - 1]][group.city[i]];

}

group.adapt = distance;

group.pAlive = 1 / (float)distance;

}

void Swap(int &a, int &b) // 交换ab值

{

int c;

c = a;

a = b;

b = c;

}

void Init() // 初始化

{

srand((unsigned int)time(0));

for (int i = 0; i < NUM_CITY; i++) // 初始化城市距离

{

for (int j = i + 1; j < NUM_CITY; j++)

{

cityDistance[i][j] = RAND(100) + 1;

cityDistance[j][i] = cityDistance[i][j];

}

}

printf("城市距离如下:\n");

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

{

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

{

if (j < i + 1)

printf(" ");

else

printf("%3d ", cityDistance[i][j]);

}

printf("\n");

}

for (int i = 0; i < MAX_SIZE; i++) // 初始化样本数列

{

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

{

g_Group[i].city[j] = j;

}

}

int r;

for (int i = 0; i < MAX_SIZE; i++) // 打乱顺序

{

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

{

r = RAND(NUM_CITY);

Swap(g_Group[i].city[j], g_Group[i].city[r]);

}

}

printf("产生初始种群如下:\n");

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

{

printf("第%d个个体:\n", i + 1);

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

{

printf("%3d ", g_Group[i].city[j]);

}

printf("\n");

}

}

void GetAliveP() // 存活率

{

float totalAlive = 0;

//选择最优部分

totalAlive = 0;

for (int i = 0; i < MAX_SIZE; i++) // 计算个体适应值

{

getFitness(g_Group[i]);

totalAlive += g_Group->pAlive;

}

for (int i = 0; i < MAX_SIZE; i++) // 矫正个体存活率 让总和为1

{

g_Group[i].pAlive /= totalAlive;

}

bestOne = 0;

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

{

if (g_Group[i].pAlive > g_Group[bestOne].pAlive)

bestOne = i;

}

printf("目前最佳个体为:%d, 其距离为%d,其轨迹如下:\n", bestOne+1, g_Group[bestOne].adapt);

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

printf("%d ", g_Group[bestOne].city[i]);

printf("\n");

}

int isOnIt(int num, int Array[NUM_CITY], int ignorePos, int pos1, int pos2) // num是否在Array[]的pos1到pos2之间 其中跳过ignorePos(该数字的原位置)

{

for (int i = pos1; i <= pos2; i++)

{

if (Array[i] == num)

return i;

}

return -1;

}

void Swap(int sel1,int sel2,int pos1, int pos2) // 交叉互换

{

int temp;

int maxSize = pos2 - pos1 + 1;

//printf("开始初步交叉互换\n");

//printf("%d %d\n", pos1, pos2);

for (int i = pos1; i <= pos2; i++)

{

temp = g_Group[sel1].city[i];

g_Group[sel1].city[i] = g_Group[sel2].city[i];

g_Group[sel2].city[i] = temp;

}

//for (int j = 0; j < NUM_CITY; j++)

//printf("%4d", g_Group[sel1].city[j]);

//printf("\n");

//for (int j = 0; j < NUM_CITY; j++)

//printf("%4d", g_Group[sel2].city[j]);

//printf("\n");

int pos;

//printf("开始矫正重复值\n");

int times = 0;

for (int i = 0; i < NUM_CITY; i++) // 矫正重复值

{

times = 0;

if (i >= pos1 && i <= pos2)

{

i = pos2;

continue;

}

do

{

times++;

pos = isOnIt(g_Group[sel1].city[i], g_Group[sel1].city, i, pos1, pos2);

if (pos != -1)

{/*

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

printf("%4d", g_Group[sel1].city[j]);

printf("\n");

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

printf("%4d", g_Group[sel2].city[j]);

printf("\n");

printf("%d %d %d %d %d\n",pos1,pos2,pos, g_Group[sel1].city[i], g_Group[sel2].city[pos]);*/

g_Group[sel1].city[i] = g_Group[sel2].city[pos];

//printf("pos:%d,pos1:%d,pos2:%d\n", pos, pos1, pos2);

}

} while (pos != -1);

do

{

pos = isOnIt(g_Group[sel2].city[i], g_Group[sel2].city, i, pos1, pos2);

if (pos != -1)

{

g_Group[sel2].city[i] = g_Group[sel1].city[pos];

//printf("pos:%d,pos1:%d,pos2:%d\n", pos, pos1, pos2);

}

} while (pos != -1);

}

//printf("交叉互换过程完毕\n");

}

void Mutation(int sel, int pos1,int pos2)//个体突变

{

int maxSize = pos2 - pos1 + 1;

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

{

Swap(g_Group[sel].city[pos1+i], g_Group[sel].city[pos2-i]);

}

}

void Genetic() // 产生下一代种群

{

int maxNum = 0, minNum = 0;

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

{

if (g_Group[i].pAlive > g_Group[maxNum].pAlive)

maxNum = i;

if (g_Group[i].pAlive < g_Group[maxNum].pAlive)

minNum = i;

}

g_Group[minNum] = g_Group[maxNum]; // 使最大直接替换最小

//printf("开始交叉\n");

// 交叉配对

int selNum;

int maxTimes = 0, nowTimes = 0;

int canSelected[MAX_SIZE]; // 可以用于交叉的个体

bool isCanSelected[MAX_SIZE];

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

{

if (i == maxNum) // 不让最优秀的个体参与配对

continue;

else if ((RAND(100)) / 100.0 < Pc) // 根据概率判断是否参与配对

{

canSelected[maxTimes++] = i;

}

}

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

{

selNum = RAND(maxTimes);

Swap(canSelected[i], canSelected[selNum]);

}

int pos1, pos2;

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

{

selNum = i + 1;

if (selNum >= maxTimes)

break;

pos1 = RAND(NUM_CITY); // 选定交叉位置

pos2 = RAND(NUM_CITY - pos1) + pos1;

if (pos1 == pos2)

{

if (pos1 > 0)

pos1--;

else

pos2++;

}/*

printf("%d与%d开始交叉互换\n", canSelected[i], canSelected[selNum]);*/

Swap(canSelected[i], canSelected[selNum], pos1, pos2);

/*

printf("第%d个体与第%d个体进行交叉配对,得到新的两个个体如下:\n", canSelected[i] + 1, canSelected[selNum] + 1);

printf("第%d个体:\n", canSelected[i] + 1);

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

printf("%4d", g_Group[canSelected[i]].city[j]);

printf("\n第%d个体:\n", canSelected[selNum] + 1);

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

printf("%4d", g_Group[canSelected[selNum]].city[j]);

printf("\nselNum:%d, maxTimes:%d\n",selNum,maxTimes);*/

}

/*

printf("开始突变\n");*/

// 突变

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

{

if (i == maxNum || i == minNum)

{

continue;

}

if (RAND(100) / 100.0 < Pm) // 符合突变概率

{

pos1 = RAND(NUM_CITY); // 选择位置

pos2 = RAND(NUM_CITY - pos1) + pos1;

if (pos1 == pos2)

{

if (pos1 > 0)

pos1--;

else

pos2++;

}

/*printf("第%d个体突变前:\n", i + 1);

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

printf("%4d", g_Group[i].city[j]);

printf("\n");*/

Mutation(i, pos1, pos2);

//printf("第%d个体突变:\n", i + 1);/*

//for (int j = 0; j < NUM_CITY; j++)

//printf("%4d", g_Group[i].city[j]);

//printf("\n");

}

}

}

void Train()

{

int nowGenerations = 0;

float totalAlive = 0;

do

{

printf("第%d代种群\n", nowGenerations + 1);

GetAliveP();// 计算存活率

Genetic();// 根据遗传规律得到下一代

nowGenerations++;

} while (nowGenerations < GENERATIONS);

printf("经过%d次繁衍,得到的优秀个体为:\n", nowGenerations);

printf("其距离为%d,其轨迹如下:\n", g_Group[bestOne].adapt);

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

printf("%d ", g_Group[bestOne].city[i]);

printf("\n");

printf("其他个体如下:\n");

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

{

printf("其距离为%d,其轨迹如下:\n", g_Group[i].adapt);

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

{

printf("%d ", g_Group[i].city[j]);

}

printf("\n");

}

}

int main()

{

Init();

Train();

return 0;

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值