智能优化算法 | 变邻域搜索算法求解TSP问题(berlin52为例) | C++

该博客介绍了使用变邻域搜索(VNS)算法来解决旅行商问题(TSP)的优化过程。通过两种邻域结构——two_opt_swap和two_h_opt_swap算子,对柏林52城市的TSP实例进行迭代优化,最终找到较优解。代码中设置迭代次数和增量成本阈值以避免早熟收敛,并展示了算法的主要流程和关键函数实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

33ab20dd35197c427583967022432873.png

VNS求解TSP问题(berlin52为例)

运行演示

源码

基于参考【1】的源码,进行了修改,加速迭代。附部分源码:

//邻域结构1 使用two_opt_swap算子     随机选择两点,区间反转。
void neighborhood_one(SOLUTION & solution, CITIES *cities)
{
  int i, k, count = 0;
  int max_no_improve = 60;//迭代60次无相对优化,就认为是最优解。7526最优解。如果不是这个解,可以增大该值。


  int inital_cost = solution.cost; //初始成本
  int now_cost = 0;
  int cur_delta = 0; //cxy新增
  //SOLUTION current_solution = solution;
  //两两节点区间反转,初次计算成本相对初始成本的增量。
  for (int i = 0; i < CITY_SIZE - 1; i++)
  {
    for (k = i + 1; k < CITY_SIZE; k++)
    {
      Delta1[i][k] = calc_delta1(i, k, solution.permutation, cities);
    }
  }
  //循环中会在选择了区间反转后重新进行成本增量矩阵的计算。
  do 
  {
    count++;
    for (i = 0; i < CITY_SIZE - 1; i++)
    {
      for (k = i + 1; k < CITY_SIZE; k++)
      {
        if (Delta1[i][k] < cur_delta)//cur_delta  //对于相对成本增量为负值的,更新当前解。如果邻域中有很多增量成本为负值,相当于只 邻域里为负值成本的最后一个有效
        {
          //current_solution = solution;
          two_opt_swap(solution.permutation, i, k); //反转当前解的 i k节点之间的区间


          now_cost = inital_cost + Delta1[i][k];//新的成本
          solution.cost = now_cost;//更新解的成本。覆盖了


          inital_cost = solution.cost;//
          cur_delta = Delta1[i][k];
           Update1(i, k, solution.permutation, cities, Delta1);//重新计算区间反转后的解的 变邻域成本增量


          count = 0; //count复位,再次从头开始寻找
          
        }


       }
      }
  }while (count <= max_no_improve);


}
//邻域结构2 使用two_h_opt_swap算子。随机选两个节点插入最前。插入操作。
void neighborhood_two(SOLUTION & solution, CITIES *cities)
{
  int i, k, count = 0;
  int max_no_improve = 60;//最大无优化次数 ,终止条件
  int inital_cost = solution.cost; //初始成本
  int now_cost = 0;
  int delta = 0;
  int cur_delta = 0;//cxy 新增
  do
  {
    count++;
    for (i = 0; i < CITY_SIZE - 1; i++)//遍历所有城市
    {
      for (k = i + 1; k < CITY_SIZE; k++)//遍历当前城市后面的 
      {
        
        delta = calc_delta2(i, k, solution.permutation, cities);//随机产生两点,塞进新排列头部。其余的按顺序往后逐个塞进去。计算新的顺序 成本改变量


        if (delta < cur_delta)//cur_delta
        {
          //cout<<"delta = " <<delta<<endl; 


          two_h_opt_swap(solution.permutation, i, k);//随机产生两点,塞进新排列头部。其余的按顺序往后逐个塞进去


          now_cost = inital_cost + delta;
          solution.cost = now_cost;


          inital_cost = solution.cost;
            cur_delta = delta;
          count = 0; //count复位
        }
      }
    }
  } while (count <= max_no_improve);
}
//VND
//best_solution最优解
//current_solution当前解
void variable_neighborhood_descent(SOLUTION & solution, CITIES * cities)
{


  SOLUTION current_solution = solution;//局部当前解=全局解
  int l = 1;
  cout  <<"=====================VariableNeighborhoodDescent=====================" << endl;
  while(true)
  {
    switch (l)
    {
      case 1://邻域1 搜索
        neighborhood_one(current_solution, cities);
        cout << setw(45) << setiosflags(ios::left)  <<"Now in neighborhood_one , current_solution = " << current_solution.cost << setw(10) << setiosflags(ios::left) << "  solution = " << solution.cost << endl;
        if (current_solution.cost < solution.cost)
        {
          solution = current_solution;//更新全局解
          l = 0;//下一轮搜索
        }
        break;
      case 2://邻域2 搜索
        neighborhood_two(current_solution, cities);
        cout << setw(45) << setiosflags(ios::left) << "Now in neighborhood_two , current_solution = " << current_solution.cost << setw(10) << setiosflags(ios::left) << "  solution = " << solution.cost << endl;
        if (current_solution.cost < solution.cost)
        {
          solution = current_solution;//更新全局解
          l = 0;//下一轮搜索
        }
        break;
      default:
        return;
    }
    l++;


  }
}
//此源码有问题,修改后可以找到7526
int main()
{


  srand((unsigned) time(0));


  SOLUTION best_solution;//最优解   排序


  random_permutation(best_solution.permutation);//生成随机初始最优排序
  best_solution.cost = cost_total(best_solution.permutation, berlin52);//初始成本,初始总路线长度


  cout << "初始总路线长度 = " << best_solution.cost << endl;


  variable_neighborhood_search(best_solution, berlin52);//执行变邻域搜索


  cout << endl << endl << "搜索完成!最优路线总长度 = " << best_solution.cost << endl;
  cout << "最优访问城市序列如下:" << endl;
  for (int i = 0; i < CITY_SIZE; i++)
  {//宽度4,左对齐,最优解顺序
    cout << setw(4) << setiosflags(ios::left) << best_solution.permutation[i];
  }


  cout << endl << endl;


  return 0;
}

参考

https://github.com/accelerate0818/VariableNeighborhoodSearchTSP

https://github.com/B06SuperLab/TSP_GA

https://www.cnblogs.com/dengfaheng/p/10852917.html 

https://cloud.tencent.com/developer/article/1548088

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值