当前位置: 首页 > news >正文

10.1 - 遗传算法(旅行商问题C#求解)

        遗传算法是模拟自然界生物进化过程的随机优化算法,通过模拟"自然选择"和"遗传机制"来寻找最优解,其中遗传机制主要依靠突变、交叉、选择这些仿生算子。

适应度生存能力解决方案的质量评分
选择自然选择选择优秀的个体进行繁殖
交叉有性繁殖组合两个个体的基因
变异基因突变随机改变个体的某些基因

一、旅行商问题

给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路

        为了简单起见:以直线上等间距的10个城市为例。最短距离就是18. 

        编程思路是:

        1. 先随机生成比如20条路线;

        2. 然后按距离排序,丢掉最长的10条;

       3. 剩下(被选择)的10条通过突变因子和交叉因子再生成10条。

       4.  (当迭代次数未完成时)返回到2. 完成一次迭代。 

【备注】如果按照50个人口来,差不多几次就可以得到最好的结果

1.1 突变因子

        把两座随机指定的城市交换位置。

 public Solution Mutate(Random random)
{
var i=random.Next(0,CityList.Count);
var j= random.Next(0, CityList.Count);
if (i == j)
{
return this;
}
var newCityList = new List<int>(CityList);
var temp = newCityList[i];
newCityList[i] = newCityList[j];
newCityList[j]= temp;
return new Solution(newCityList);
}

2.交叉算子

        由父A母B的各一部分交叉组成;思路是:随机从B中取一段放到child中,然后把A中的所有不在子类的按顺序填充到child中。作为进化后的        

//把另外一个的城市序列的一段拷贝过来,并且把本序列的其余部分按顺序拷贝到child中

 public Solution CrossOver(Random random,Solution solution)
{
int length = this.CityList.Count;
// 随机选择两个交叉点
int point1 = random.Next(0, length - 1);
int point2 = random.Next(point1 + 1, length);
int[] child1 = new int[length];
FillArray(child1, -1);
// 复制中间段
for (int i = point1; i <= point2; i++)
{
child1[i] = solution.CityList[i];

     }
FillRemainingPositions(this.CityList,  child1, point1, point2);
return new Solution(child1);

 }        

//按顺序把parent中不在child中的元素填充过来。

 private static void FillRemainingPositions(List<int> parent,
int[] child, int start, int end)
{

     var remainElement = parent.Where(x => child.Contains(x) == false).Select(x => x).ToList();
if (remainElement.Any() == false)
return;

     int j = 0;
for (int i = 0; i < child.Length; i++)
{
if (i >= start && i <= end) continue;
child[i] = remainElement[j++];

     }
}

3.实际的一段截图如下:

二、代码

   /// <summary>/// trip route,/// </summary>public class TripRoute{/// <summary>/// Map is distance between points, Map[2,3] means distance beween point2-point3./// </summary>public static double[,] Map { get;set; }public TripRoute(double[,] map){Map = map;}/// <summary>/// calculate the distance between the point series./// for example: 1-5-2-3;    1-5;5-2;2-3;/// </summary>/// <param name="solution"></param>public static void CalculateDistance(Solution solution){var result = 0.0;for(int i = 0; i <solution.CityList.Count-1; i++){result += Map[solution.CityList[i], solution.CityList[i + 1]];}result+= Map[0, solution.CityList.Count-1]; //最后回到原点solution.Distances = result;}}public class Solution :IComparable<Solution>{public List<int> CityList { get; set; }public double Distances { get; set; }/// <summary>/// Get a solution for travel route/// </summary>/// <param name="cityList"></param>public Solution(IEnumerable<int> cityList){CityList = new List<int>(cityList);TripRoute.CalculateDistance(this);}/// <summary>/// 变异\突变;/// 交换两个城市在序列中的位置/// </summary>/// <param name="random"></param>/// <returns></returns>public Solution Mutate(Random random){var i=random.Next(0,CityList.Count);var j= random.Next(0, CityList.Count);if (i == j){return this;}var newCityList = new List<int>(CityList);var temp = newCityList[i];newCityList[i] = newCityList[j];newCityList[j]= temp;return new Solution(newCityList);}/// <summary>/// 交叉算子,一个基因的前半部分和后一个基因的后一半部分组合/// </summary>/// <param name="random"></param>/// <param name="solution"></param>/// <returns></returns>public Solution CrossOver(Random random,Solution solution){int length = this.CityList.Count;// 随机选择两个交叉点int point1 = random.Next(0, length - 1);int point2 = random.Next(point1 + 1, length);int[] child1 = new int[length];FillArray(child1, -1);// 复制中间段for (int i = point1; i <= point2; i++){child1[i] = solution.CityList[i];}FillRemainingPositions(this.CityList,  child1, point1, point2);return new Solution(child1);}        /// <summary>/// 按顺序把parent中不在child中的元素填充过来。/// </summary>/// <param name="parent"></param>/// <param name="child"></param>/// <param name="start"></param>/// <param name="end"></param>private static void FillRemainingPositions(List<int> parent,int[] child, int start, int end){var remainElement = parent.Where(x => child.Contains(x) == false).Select(x => x).ToList();if (remainElement.Any() == false)return;int j = 0;for (int i = 0; i < child.Length; i++){if (i >= start && i <= end) continue;child[i] = remainElement[j++];}}public static void FillArray<T>(T[] array, T value){for (int i = 0; i < array.Length; i++){array[i] = value;}}public int CompareTo(Solution other){if (other == null) return 1;return this.Distances.CompareTo(other.Distances);}public override string ToString(){StringBuilder sb = new StringBuilder();foreach(int i in this.CityList){sb.Append( string.Format("{0}, ", i));}sb.Append("距离:"+this.Distances.ToString());return sb.ToString();}}public class GeneticAlgorithmTsp{public int Iterations { get; set; }public TripRoute Tsp { get; set; }public List<Solution> Population { get; set; }public int Size;private static readonly Random random = new Random();public GeneticAlgorithmTsp(int iterations, TripRoute tsp, int size){Iterations = iterations;Tsp = tsp;Size = size;Population = new List<Solution>();}public Solution Execute(){InitPopulation();var i = 0;while(i<Iterations){var selected = ChooseBest();var newPopulation = Evolution(selected as List<Solution>);MergePopulation(newPopulation);i++;Logger.Record("----------------------");Logger.Record( string.Format("第{0}次迭代,种群数量{1},最优距离{2},种群如下", i,Population.Count , Population.First().Distances));foreach (var item in Population){Logger.Record(item.ToString());}Logger.Record("----------------------");}return Population.First();}/// <summary>/// 初始化种群/// </summary>private void InitPopulation(){var i = 0;while (i < Size){Population.Add(RandomSolution(TripRoute.Map.GetLength(0)));i++;}Logger.Record("初始化种群情况:");foreach(var item in Population){Logger.Record(item.ToString());}}/// <summary>/// 随机生成顺序/// </summary>/// <param name="n"></param>/// <returns></returns>private Solution RandomSolution(int n){var result = new List<int>();var range = Enumerable.Range(0, n).ToList();while (range.Count > 0){var index = random.Next(0, range.Count);result.Add(range[index]);range.RemoveAt(index);}return new Solution(result);}/// <summary>/// 人口合并/// </summary>/// <param name="newPopulation"></param>private void MergePopulation(IEnumerable<Solution> newPopulation){Population.AddRange(newPopulation);Population.Sort();Population = Population.GetRange(0, Size);}/// <summary>/// 使用交换或变异的办法产生新的元素/// </summary>/// <param name="selected"></param>/// <returns></returns>private IEnumerable<Solution> Evolution(List<Solution> selected){var result = new List<Solution>();for(var i=0;i<selected.Count;i++){result.Add(random.NextDouble() <= 0.4? selected[i].Mutate(random) : selected[i].CrossOver(random, selected[random.Next(0, selected.Count)]));}Logger.Record("-------------:");Logger.Record( string.Format("新进化出的人口,数量{0},情况如下:",result.Count));foreach(Solution s in result){Logger.Record(s.ToString());}return result;}/// <summary>/// 选择表现好的,即总数的一半/// </summary>/// <returns></returns>private IEnumerable<Solution>   ChooseBest(){Population.Sort();Logger.Record("-------------:");Logger.Record("选择最好的一半,丢失的如下:");for(int i= Size / 2;i<Size;i++){Logger.Record(Population[i].ToString());}return Population.GetRange(0, Size / 2);}}static void Main(string[] args){var map = new double[,]{{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9  },	//城市距离矩阵{  1, 0, 1, 2, 3, 4, 5, 6, 7, 8  },{  2, 1, 0, 1, 2, 3, 4, 5, 6, 7  },{  3, 2, 1, 0, 1, 2, 3, 4, 5, 6  },{  4, 3, 2, 1, 0, 1, 2, 3, 4, 5  },{  5, 4, 3, 2, 1, 0, 1, 2, 3, 4  },{  6, 5, 4, 3, 2, 1, 0, 1, 2, 3  },{  7, 6, 5, 4, 3, 2, 1, 0, 1, 2  },{  8, 7, 6, 5, 4, 3, 2, 1, 0, 1  },{  9, 8, 7, 6, 5, 4, 3, 2, 1, 0  }};var ga = new GeneticAlgorithmTsp(100, new TripRoute(map), 20);var best = ga.Execute();Console.WriteLine("best solution:");foreach (var d in best.CityList)Console.Write("{0}, ", d);Console.WriteLine("\n" + "fitness:{0}", best.Distances);Console.Read();return;       }


文章转载自:

http://tVsxOfmv.pshcd.cn
http://KWlewFqX.pshcd.cn
http://af5zj9jx.pshcd.cn
http://yiR0n7Xo.pshcd.cn
http://LVg8pbCK.pshcd.cn
http://Pt1l7sNd.pshcd.cn
http://75oR27sX.pshcd.cn
http://l1ynFAgd.pshcd.cn
http://YdQuLcYS.pshcd.cn
http://TVn8rw67.pshcd.cn
http://xwZ92NnI.pshcd.cn
http://C3F6JVjm.pshcd.cn
http://YUC19BFG.pshcd.cn
http://VawNPJkc.pshcd.cn
http://U5Mko7sA.pshcd.cn
http://Snp2w8bO.pshcd.cn
http://pl1OIaDX.pshcd.cn
http://TRQN67HV.pshcd.cn
http://uI9NhOC1.pshcd.cn
http://703RPAJr.pshcd.cn
http://VHfx6YRE.pshcd.cn
http://pBFcmKCt.pshcd.cn
http://N7obqe2j.pshcd.cn
http://ubei5lkK.pshcd.cn
http://IEb0dTlL.pshcd.cn
http://YXRCXsol.pshcd.cn
http://OoqRDC3a.pshcd.cn
http://XVQQ8h9a.pshcd.cn
http://ljkdfGZV.pshcd.cn
http://begU7nVq.pshcd.cn
http://www.dtcms.com/a/387110.html

相关文章:

  • Java 集合入门:从基础到实战的完整知识指南
  • 《过山车大亨3 完整版》PSXbox版下月推出 预告片赏
  • P1107题解
  • 多目标数据关联算法MATLAB实现
  • 战略推理AI Agents:组装LLM+因果推断+SHAP
  • 【CVPR 2016】基于高效亚像素卷积神经网络的实时单幅图像与视频超分辨率
  • 基于STM32的LED实战 -- 流水灯、呼吸灯、流水呼吸灯
  • 【数据结构】——队列,栈(基于链表或数组实现)
  • 任天堂官网更新!“任亏券”不支持兑换NS2专用游戏
  • 大模型数据整理器打包及填充、Flash Attention 2解析(97)
  • 48v转12v芯片48v转5v电源芯片AH7691D
  • Oracle Database 23ai 内置 SQL 防火墙启用
  • MySQL 31 误删数据怎么办?
  • 微前端面试题及详细答案 88道(09-18)-- 核心原理与实现方式
  • VBA技术资料MF362:将窗体控件添加到字典
  • 【Leetcode】高频SQL基础题--1321.餐馆营业额变化增长
  • Redis 中 Intset 的内存结构与存储机制详解
  • uniapp打包前端项目
  • cka解题思路1.32-3
  • 如何解决模型的过拟合问题?
  • 2025牛客周赛108场e题
  • 【课堂笔记】复变函数-2
  • 25、优化算法与正则化技术:深度学习的调优艺术
  • qt QCategoryAxis详解
  • 云游戏时代,游戏盾如何保障新型业务的流畅体验
  • 【Block总结】LRSA,用于语义分割的低分辨率自注意力|TPAMI 2025
  • PY32MD310单片机介绍 电机控制专用,内置三相半桥栅极驱动器
  • Ubuntu服务器挖矿病毒清理
  • 【数据结构】——二叉树
  • 《怪物猎人 荒野》总整理:预载和开放时间、登场怪物