其奈公何 发表于 2023-4-1 00:21:41

dalao看看 蚁群算法求解TSP问题

H.:
#pragma warning(disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>

#define M 30//蚂蚁的数量
#define N 20//城市的数量
#define R 100 //迭代次数
#define IN 1//初始化的信息素的量
#define MAX 0x7fffffff //定义最大值

struct coordinate {
    char name;//城市名
    int x;      //城市相对横坐标
    int y;      //城市相对纵坐标
};
struct coordinate city = { {'a',88,16},{'b',42,76},{'c',5.76},{'d',69,13},{'e',73,56},{'f',100,100},{'g',22,92},{'h',48,74},{'i',73,46},{'j',39,1},{'k',51,75},{'l',92,2},{'m',101,44},{'n',55,26},{'o',71,27},{'p',42,81},{'q',51,91},{'r',89,54},{'s',33,18},{'t',40,78} };


double graph;//储存城市之间的距离的邻接矩阵,自己到自己记作MAX
double phe;//每条路径上的信息素的量
double add;//代表相应路径上的信息素的增量
double yita; //启发函数,yita=1/graph
int vis;//标记已经走过的城市
int map;//map记录第K只蚂蚁走的路线
double solution; //记录某次循环中每只蚂蚁走的路线的距离
int bestway; //记录最近的那条路线
double bestsolution = MAX;
int NcMax; //代表迭代次数,理论上迭代次数越多所求的解更接近最优解,最具有说服力
double alpha, betra, rou, Q;

void Initialize(); //信息初始化
void GreateGraph(); //根据坐标信息建图
double Distance(int* p); //计算蚂蚁所走的路线的总长度
void Result(); //将结果保存到out.txt中

void Initialize()//信息初始化
{
    alpha = 4; betra = 5; rou = 0.5; Q = 100;
    NcMax = R;
    return;
}

void GreateGraph()//根据坐标信息建图
{
    int i, j;
    double d;
    for (i = 0; i < N - 1; ++i)
    {
      graph = MAX;   //自己到自己标记为无穷大
      for (j = i + 1; j < N; ++j)
      {
            d = (double)((city.x - city.x) * (city.x - city.x) + (city.y - city.y) * (city.y - city.y));
            graph = graph = sqrt(d);
      }
    }
    graph = MAX;
    return;
}

double Distance(int* p)//计算蚂蚁所走总长度
{
    double d = 0;
    int i;
    for (i = 0; i < N - 1; ++i)
    {
      d += graph[*(p + i)][*(p + i + 1)];
    }
    d += graph[*(p + i)][*(p)];
    return d;
}void Result()//将结果保存到out.txt中
{
    FILE* fl;
    int i;
    fl = fopen("ou

H.:
fl = fopen("out.txt", "a");//将结果保存在out.txt这个文件里面
    fprintf(fl, "%s\n", "本次算法中的各参数如下:");
    fprintf(fl, "alpha=%.3lf, betra=%.3lf, rou=%.3lf, Q=%.3lf\n", alpha, betra, rou, Q);
    fprintf(fl, "%s %d\n", "本次算法迭代次数为:", NcMax);
    fprintf(fl, "%s %.4lf\n", "本算法得出的最短路径长度为:", bestsolution);
    fprintf(fl, "%s\n", "本算法求得的最短路径为:");
    for (i = 0; i < N; ++i)
      fprintf(fl, "%s →", city].name);
    fprintf(fl, "%s", city].name);
    fprintf(fl, "\n\n\n");
    fclose(fl);
    return;
}

int main()
{
    int NC = 0;
    int i, j, k;
    int s;
    double drand, pro, psum;
    Initialize();//信息初始化
    GreateGraph();//根据坐标信息建图
    for (i = 0; i < N; ++i)
    {
      for (j = 0; j < N; ++j)
      {
            phe = IN; //信息素初始化
            if (i != j)
                yita = 100.0 / graph;//期望值,与距离成反比
      }
    }
    memset(map, -1, sizeof(map));//把蚂蚁走的路线置空
    memset(vis, 0, sizeof(vis));//0表示未访问,1表示已访问
    srand(time(NULL));
    while (NC++ <= NcMax)
    {
      for (k = 0; k < M; ++k)
      {
            map = (k + NC) % N; //给每只蚂蚁分配一个起点,并且保证起点在N个城市里
            vis] = 1; //将起点标记为已经访问
      }
      s = 1;
      while (s < N)
      {
            for (k = 0; k < M; ++k)
            {
                psum = 0;

                for (j = 0; j < N; ++j)
                {
                  if (vis == 0)
                  {
                        psum += pow(phe], alpha) * pow(yita], betra);
                  }
                }
                drand = (double)(rand());
                drand /= 5000.0;//生成一个小于1的随机数
                pro = 0;
                for (j = 0; j < N; ++j)
                {
                  if (vis == 0)
                        pro += pow(phe], alpha) * pow(yita], betra) / psum;
                  if (pro > drand)
                        break;

H.:
}
                vis = 1;//将走过的城市标记起来
                map = j;//记录城市的顺序
            }
            s++;
      }
      memset(add, 0, sizeof(add));
      for (k = 0; k < M; ++k)//计算本次中的最短路径//
      {
            solution = Distance(map);//蚂蚁k所走的路线的总长度
            if (solution < bestsolution)
            {
                bestsolution = solution;
                for (i = 0; i < N; ++i)
                  bestway = map;
            }
      }
      for (k = 0; k < M; ++k)
      {
            for (j = 0; j < N - 1; ++j)
            {
                add]] += Q / solution;
            }
            add += Q / solution;
      }
      for (i = 0; i < N; ++i)
      {
            for (j = 0; j < N; ++j)
            {
                phe = phe * rou + add;
                if (phe < 0.0001)//设立一个下界
                  phe = 0.0001;
                else if (phe > 20)//设立一个上界,防止启发因子的作用被淹没
                  phe = 20;
            }
      }
      memset(vis, 0, sizeof(vis));
      memset(map, -1, sizeof(map));
    }
    Result();
    printf("Result is saved in out.txt\n");
    return 0;
}

其奈公何 发表于 2023-4-1 00:23:22

呜呜呜不知道为什么最短路径过程和长度大小一直错误

isdkz 发表于 2023-4-1 02:48:49

两个问题:

1、你在城市数组初始化中城市名用的是字符,所以城市结构体定义中,城市名应该使用char类型而不是char[]。

将结构体定义更改为:

struct coordinate {
    char name;//城市名
    int x;      //城市相对横坐标
    int y;      //城市相对纵坐标
};

2、在输出结果时,需要将城市名作为字符输出。将Result函数中的fprintf语句更改为:

for (i = 0; i < N; ++i)
    fprintf(fl, "%c →", city].name);
fprintf(fl, "%c", city].name);

其奈公何 发表于 2023-4-1 11:24:43

isdkz 发表于 2023-4-1 02:48
两个问题:

1、你在城市数组初始化中城市名用的是字符,所以城市结构体定义中,城市名应该使用char类型 ...

#pragma warning(disable:4996)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>
#include<string.h>

#define M 30//蚂蚁的数量
#define N 20//城市的数量
#define R 100 //迭代次数
#define IN 1//初始化的信息素的量
#define MAX 0x7fffffff //定义最大值

struct coordinate {
    char name;//城市名
    int x;      //城市相对横坐标
    int y;      //城市相对纵坐标
};
struct coordinate city = { {'a',88,16},{'b',42,76},{'c',5.76},{'d',69,13},{'e',73,56},{'f',100,100},{'g',22,92},{'h',48,74},{'i',73,46},{'j',39,1},{'k',51,75},{'l',92,2},{'m',101,44},{'n',55,26},{'o',71,27},{'p',42,81},{'q',51,91},{'r',89,54},{'s',33,18},{'t',40,78} };


double graph;//储存城市之间的距离的邻接矩阵,自己到自己记作MAX
double phe;//每条路径上的信息素的量
double add;//代表相应路径上的信息素的增量
double yita; //启发函数,yita=1/graph
int vis;//标记已经走过的城市
int map;//map记录第K只蚂蚁走的路线
double solution; //记录某次循环中每只蚂蚁走的路线的距离
int bestway; //记录最近的那条路线
double bestsolution = MAX;
int NcMax; //代表迭代次数,理论上迭代次数越多所求的解更接近最优解,最具有说服力
double alpha, betra, rou, Q;

void Initialize(); //信息初始化
void GreateGraph(); //根据坐标信息建图
double Distance(int* p); //计算蚂蚁所走的路线的总长度
void Result(); //将结果保存到out.txt中

void Initialize()//信息初始化
{
    alpha = 4; betra = 5; rou = 0.5; Q = 100;
    NcMax = R;
    return;
}

void GreateGraph()//根据坐标信息建图
{
    int i, j;
    double d;
    for (i = 0; i < N - 1; ++i)
    {
      graph = MAX;   //自己到自己标记为无穷大
      for (j = i + 1; j < N; ++j)
      {
            d = (double)((city.x - city.x) * (city.x - city.x) + (city.y - city.y) * (city.y - city.y));
            graph = graph = sqrt(d);
      }
    }
    graph = MAX;
    return;
}

double Distance(int* p)//计算蚂蚁所走总长度
{
    double d = 0;
    int i;
    for (i = 0; i < N - 1; ++i)
    {
      d += graph[*(p + i)][*(p + i + 1)];
    }
    d += graph[*(p + i)][*(p)];
    return d;
}
void Result()//将结果保存到out.txt中
{
    FILE* fl;
    int i;
        fl = fopen("out.txt", "a");//将结果保存在out.txt这个文件里面
    fprintf(fl, "%s\n", "本次算法中的各参数如下:");
    fprintf(fl, "alpha=%.3lf, betra=%.3lf, rou=%.3lf, Q=%.3lf\n", alpha, betra, rou, Q);
    fprintf(fl, "%s %d\n", "本次算法迭代次数为:", NcMax);
    fprintf(fl, "%s %.4lf\n", "本算法得出的最短路径长度为:", bestsolution);
    fprintf(fl, "%s\n", "本算法求得的最短路径为:");
   for (i = 0; i < N; i++)
    fprintf(fl, "%c →", city].name);
fprintf(fl, "%c", city].name);
    fprintf(fl, "\n\n\n");                  
    fclose(fl);
    return;
}

int main()
{
    int NC = 0;
    int i, j, k;
    int s;
    double drand, pro, psum;
    Initialize();//信息初始化
    GreateGraph();//根据坐标信息建图
    for (i = 0; i < N; ++i)
    {
      for (j = 0; j < N; ++j)
      {
            phe = IN; //信息素初始化
            if (i != j)
                yita = 100.0 / graph;//期望值,与距离成反比
      }
    }
    memset(map, -1, sizeof(map));//把蚂蚁走的路线置空
    memset(vis, 0, sizeof(vis));//0表示未访问,1表示已访问
    srand(time(NULL));
    while (NC++ <= NcMax)
    {
      for (k = 0; k < M; ++k)
      {
            map = (k + NC) % N; //给每只蚂蚁分配一个起点,并且保证起点在N个城市里
            vis] = 1; //将起点标记为已经访问
      }
      s = 1;
      while (s < N)
      {
            for (k = 0; k < M; ++k)
            {
                psum = 0;

                for (j = 0; j < N; ++j)
                {
                  if (vis == 0)
                  {
                        psum += pow(phe], alpha) * pow(yita], betra);
                  }
                }
                drand = (double)(rand());
                drand /= 5000.0;//生成一个小于1的随机数
                pro = 0;
                for (j = 0; j < N; ++j)
                {
                  if (vis == 0)
                        pro += pow(phe], alpha) * pow(yita], betra) / psum;
                  if (pro > drand)
                        break;


}
                vis = 1;//将走过的城市标记起来
                map = j;//记录城市的顺序
            }
            s++;
      }
      memset(add, 0, sizeof(add));
      for (k = 0; k < M; ++k)//计算本次中的最短路径//
      {
            solution = Distance(map);//蚂蚁k所走的路线的总长度
            if (solution < bestsolution)
            {
                bestsolution = solution;
                for (i = 0; i < N; ++i)
                  bestway = map;
            }
      }
      for (k = 0; k < M; ++k)
      {
            for (j = 0; j < N - 1; ++j)
            {
                add]] += Q / solution;
            }
            add += Q / solution;
      }
      for (i = 0; i < N; ++i)
      {
            for (j = 0; j < N; ++j)
            {
                phe = phe * rou + add;
                if (phe < 0.0001)//设立一个下界
                  phe = 0.0001;
                else if (phe > 20)//设立一个上界,防止启发因子的作用被淹没
                  phe = 20;
            }
      }
      memset(vis, 0, sizeof(vis));
      memset(map, -1, sizeof(map));
    }
    Result();
    printf("Result is saved in out.txt\n");
    return 0;
}
不知道为什么过程的路径还是打不出来

歌者文明清理员 发表于 2023-4-2 18:10:44

这段程序实现了蚁群优化算法来解决旅行商问题。根据题目描述,程序的问题可能出现在计算路径长度的函数Distance和选择下一个城市的过程中。

在Distance函数中,需要确保每只蚂蚁都走完所有城市并回到起点。当前程序的实现方式是在s=N-1时,循环结束,但此时蚂蚁还没有回到起点,因此应该将计算距离的代码块放在while循环外面,并且最后需要加上回到起点的距离。以下是修改后的代码:

```c
double Distance(int* p) // 计算蚂蚁所走的路线的总长度
{
    double d = 0;
    int i;
    for (i = 0; i < N - 1; ++i)
    {
      d += graph[*(p + i)][*(p + i + 1)];
    }
    d += graph[*(p + i)][*(p)];
    return d;
}
```

在选择下一个城市的过程中,程序采用轮盘赌的方式,但可能存在一些细节问题导致选择不够合理。可以尝试使用其他选择策略,例如贪心选择、最大信息素选择等。这里给出一种基于信息素和启发式信息的选择方法:在未访问的城市中,按照信息素和启发式信息的加权得分进行排序,然后以一定概率选择得分较高的城市。以下是代码实现:

```c
double P;

// 计算每个未访问城市的得分
for (j = 0; j < N; ++j)
{
    if (vis == 1) // 已访问过的城市不考虑
    {
      P = 0;
    }
    else
    {
      P = pow(phe], alpha) * pow(yita], betra);
    }
}

// 按得分从高到低排序
int index;
for (j = 0; j < N; ++j)
{
    index = j;
}
for (i = 0; i < N - 1; ++i)
{
    for (j = i + 1; j < N; ++j)
    {
      if (P] < P])
      {
            int t = index;
            index = index;
            index = t;
      }
    }
}

// 选择下一个城市
if (drand <= randChooseProb)
{
    j = index;
}
else
{
    double proSum = 0;
    for (j = 0; j < N - 1; ++j)
    {
      proSum += P];
    }
    double threshold = drand * proSum;
    pro = 0;
    for (j = 0; j < N - 1; ++j)
    {
      pro += P];
      if (pro >= threshold)
      {
            break;
      }
    }
    j = index;
}
```

其中,alpha和beta分别为信息素和启发式信息的权重系数,randChooseProb是以一定概率随机选择下一个城市的概率。
页: [1]
查看完整版本: dalao看看 蚁群算法求解TSP问题