C#中ShuffleList函数因断点位置不同输出异常求助
旅行商问题遗传算法随机排列重复问题排查
问题描述
在C#实现旅行商问题的遗传算法时,RandomInitialPopulation函数生成初始种群出现异常:无断点运行时,所有个体的路径排列完全相同,总距离一致;但在ShuffleList的return语句处设置断点逐步执行时,能生成不同的随机排列,符合预期。
相关代码如下:
种群生成与洗牌函数
private List<PopulationMember> RandomInitialPopulation(List<float[]> xyCoordinates, int populationSize) { List<PopulationMember> population = new List<PopulationMember>(); for (int i = 0; i < populationSize; i++) { PopulationMember populationMember = new PopulationMember(); populationMember.Path = ShuffleList(xyCoordinates); populationMember.TotalDistance = GetPathDistance(populationMember.Path); population.Add(populationMember); } return population; } private List<float[]> ShuffleList(List<float[]> arrayToShuffle) { List<float[]> tempCollection = new List<float[]>(arrayToShuffle); List<float[]> shuffledXYCoordinatesArray = new List<float[]>(); Random rnd = new Random(); while (tempCollection.Count > 0) { int num = rnd.Next(tempCollection.Count); shuffledXYCoordinatesArray.Add(tempCollection.ElementAt(num)); tempCollection.RemoveAt(num); } return shuffledXYCoordinatesArray; }
PopulationMember类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TravelingSalesman { public class PopulationMember { public List<float[]> Path { get; set; } public float TotalDistance { get; set; } } }
问题原因
问题核心在于ShuffleList函数内每次调用都实例化Random对象:
- C#中
Random默认以系统时钟的当前时间作为种子值。 - 无断点时循环执行速度极快,多次实例化
Random的时间间隔极短,导致种子值完全相同,生成的随机序列一致,最终洗牌结果重复。 - 断点调试时,每次执行有明显时间停顿,系统时钟已更新,
Random的种子值不同,因此生成的随机序列不同,洗牌结果正常。
解决方案
将Random实例的创建移到循环或ShuffleList函数外部,确保整个种群生成过程中只用一个Random实例,避免重复种子值。
修改方案1:将Random作为类成员变量
在类中定义一个Random字段,所有洗牌操作共用同一个实例:
private readonly Random _rnd = new Random(); private List<float[]> ShuffleList(List<float[]> arrayToShuffle) { List<float[]> tempCollection = new List<float[]>(arrayToShuffle); List<float[]> shuffledXYCoordinatesArray = new List<float[]>(); while (tempCollection.Count > 0) { int num = _rnd.Next(tempCollection.Count); shuffledXYCoordinatesArray.Add(tempCollection.ElementAt(num)); tempCollection.RemoveAt(num); } return shuffledXYCoordinatesArray; }
修改方案2:在RandomInitialPopulation中创建Random并传入ShuffleList
private List<PopulationMember> RandomInitialPopulation(List<float[]> xyCoordinates, int populationSize) { List<PopulationMember> population = new List<PopulationMember>(); Random rnd = new Random(); // 只创建一次Random实例 for (int i = 0; i < populationSize; i++) { PopulationMember populationMember = new PopulationMember(); populationMember.Path = ShuffleList(xyCoordinates, rnd); populationMember.TotalDistance = GetPathDistance(populationMember.Path); population.Add(populationMember); } return population; } private List<float[]> ShuffleList(List<float[]> arrayToShuffle, Random rnd) { List<float[]> tempCollection = new List<float[]>(arrayToShuffle); List<float[]> shuffledXYCoordinatesArray = new List<float[]>(); while (tempCollection.Count > 0) { int num = rnd.Next(tempCollection.Count); shuffledXYCoordinatesArray.Add(tempCollection.ElementAt(num)); tempCollection.RemoveAt(num); } return shuffledXYCoordinatesArray; }
验证效果
修改后,无断点运行时Random实例的种子值唯一,每次洗牌都会生成不同的随机序列,种群中每个个体的路径排列和总距离会呈现差异,符合遗传算法初始种群的随机性要求。
内容的提问来源于stack exchange,提问作者gummy714
相关产品推荐
相关产品推荐

