You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:05:18