首页 > 解决方案 > 如何在 C# 中解决应用程序响应问题

问题描述

我正在尝试在 C# 中实现遗传算法。遗传有交叉法和变异法。种群大小为 5 条染色体,其中每条染色体是整数的二维数组(矩阵 10x10)遗传应循环 50 次,并在每个循环中调用交叉和变异,如下所示:

  DateTime startTiming = DateTime.Now;

        TimeSpan startGenetic;


        // Make a population for each layer - as we have 4 layers, thus 4 population arrays after the intial eavaluation for the intial population and have differernt values in the aterations > 1 
        static List<int[,]> populationLayer1 = new List<int[,]>();
        static List<int[,]> populationLayer2 = new List<int[,]>();
        static List<int[,]> populationLayer3 = new List<int[,]>();
        static List<int[,]> populationLayer4 = new List<int[,]>();

        // 4 layers - we need 4 arrays 
        double[,] FitnessValLayer1 = new double[5, 2]; // for all "5" chromosome we store "2" Values : (Fitness Value - Fitness Ratio) in each layer (as we have 4 layers)
        double[,] FitnessValLayer2 = new double[5, 2]; // for all "5" chromosome we store "2" Values : (Fitness Value - Fitness Ratio) in each layer (as we have 4 layers)
        double[,] FitnessValLayer3 = new double[5, 2]; // for all "5" chromosome we store "2" Values : (Fitness Value - Fitness Ratio) in each layer (as we have 4 layers)
        double[,] FitnessValLayer4 = new double[5, 2]; // for all "5" chromosome we store "2" Values : (Fitness Value - Fitness Ratio) in each layer (as we have 4 layers)

        // 4 RouletteWeel values because of the 4 layers
        int[] RouletteWheelLayer1 = new int[10];
        int[] RouletteWheelLayer2 = new int[10];
        int[] RouletteWheelLayer3 = new int[10];
        int[] RouletteWheelLayer4 = new int[10];

        public async Task Genetic_Algorithm(List<int[,]> population)

        {

            cancelSource = new CancellationTokenSource();

            //In this step just duplicate the initial population 
            populationLayer1 = population.ToList();
            populationLayer2 = population.ToList();
            populationLayer3 = population.ToList();
            populationLayer4 = population.ToList();

            int round = 0;



            for (geneticIteration = 0; geneticIteration < minIteration; geneticIteration++)
            {


                round = geneticIteration;

                //----------------------//
                //Calculate Fitness 
                try
                {
                    // Calculate the fitness Function and the Fitness Ratio
                    await FitnessFunctionAsync(populationLayer1, populationLayer2, populationLayer3, populationLayer4, cancelSource.Token); // Fitness Function
                }

                catch (Exception ex)
                {

                    // Write output to the file.
                    Trace.Write("when calling (FitnessFunctionAsync)..." + ex.Message);
                    Trace.Flush();

                }

                //----------------------//
                // To Do : 
                //get 4 arrays for the fitness for each layer 


                //----------------------//
                // Note : Each layer has different values for fitness so the changes on the population will not be the same in the 4 layers 
                //---------------------//

                    //RouletteWeel 
                    RouletteWheelLayer1 = RouletteWheel_Selection(FitnessValLayer1);
                    RouletteWheelLayer2 = RouletteWheel_Selection(FitnessValLayer2);
                    RouletteWheelLayer3 = RouletteWheel_Selection(FitnessValLayer3);
                    RouletteWheelLayer4 = RouletteWheel_Selection(FitnessValLayer4);


                    //Crossover 
                   // populationLayer1 = CrosssOver(RouletteWheelLayer1, populationLayer1);
                    //populationLayer2 = CrosssOver(RouletteWheelLayer2, populationLayer2);
                   // populationLayer3 = CrosssOver(RouletteWheelLayer3, populationLayer3);
                    //populationLayer4 = CrosssOver(RouletteWheelLayer4, populationLayer4);

                    //Mutation 
                    //populationLayer1 = Mutation(RouletteWheelLayer1, populationLayer1);
                   // populationLayer2 = Mutation(RouletteWheelLayer2, populationLayer2);
                   // populationLayer3 = Mutation(RouletteWheelLayer3, populationLayer3);
                    //populationLayer4 = Mutation(RouletteWheelLayer4, populationLayer4);


                    // 4 layers - re-intialize  
                     FitnessValLayer1 = new double[5, 2]; 
                     FitnessValLayer2 = new double[5, 2]; 
                     FitnessValLayer3 = new double[5, 2]; 
                     FitnessValLayer4 = new double[5, 2]; 

                    // 4 RouletteWeel - re-intialize 
                     RouletteWheelLayer1 = new int[10];
                     RouletteWheelLayer2 = new int[10];
                     RouletteWheelLayer3 = new int[10];
                     RouletteWheelLayer4 = new int[10];


            }


            InvokeUpdateControls();


        }

不幸的是,当实现交叉或突变时,即满足概率时,我的应用程序没有响应。以下是两种方法:

public List<int[,]> CrosssOver(int[] RouletteWheel, List<int[,]> population)
        {


            double rndNumber1 = 0.0;

            int rndNumber2 = 0;

            Random rnd = new Random();

            int chrom1 = 0;

            int chrom2 = 0;



            for (int i = 0; i < population.Count; i++) // For all Chromosomes
            {
                rndNumber1 = rnd.Next(0, 11) / 10.00; // generate a random number to check the probability for crossover

                chrom1 = RouletteWheel[rnd.Next(0, 10)];

                chrom2 = RouletteWheel[rnd.Next(0, 10)];

                if (rndNumber1 <= Pc) /* check if we will do Crossover */
                {

                    rndNumber2 = rnd.Next(0, rows - 1); // determine the crossover point randomly by generating number between 0 and rows-1


                    for (int j = 0; j < rows; j++)
                    {


                        for (int v = 0; v < columns; v++)
                        {



                            if (j == rndNumber2) /* copy from same chromosome */
                            {

                                try
                                {
                                    population[chrom1][j, v] = population[chrom2][j, v];
                                }

                                catch (Exception ex)
                                {
                                    // Write output to the file.
                                    Trace.Write("crossover..." + ex.Message);
                                    Trace.Flush();
                                    return population;

                                }

                            }


                        }

                    }

                }

            }



            return population;

        } // end-cross-over

变异方法:

 public List<int[,]> Mutation(int[] RouletteWheel, List<int[,]> population)
        {

            double rndNumber1 = 0.0;

            int chrom1 = 0;

            int rndNumber2 = 0;

            Random rnd = new Random();


            for (int i = 0; i < population.Count; i++) // For all Chromosomes
            {
                rndNumber1 = rnd.Next(0, 11) / 100.00; // generate a random number between 0 and 10 and divide result by 100

                chrom1 = RouletteWheel[rnd.Next(0, 10)];

                if (rndNumber1 <= Pm) /* check if we will do Crossover */
                {

                    rndNumber2 = rnd.Next(0, rows); // determine the crossover point randomly by generating number between 0 and rows -1 


                    for (int j = 0; j < rows; j++)
                    {


                        for (int v = 0; v < columns; v++)
                        {



                            if (j == rndNumber2) /* Mutate the cell that is equal to 1 */
                            {
                                try
                                {
                                    if (population[chrom1][j, v] == 0)
                                    {
                                        population[chrom1][j, v] = 1;
                                    }

                                }

                                catch (Exception ex)
                                {
                                    // Write output to the file.
                                    Trace.Write("mutation..." + ex.Message);
                                    Trace.Flush();
                                    return population;

                                }

                            }


                        }

                    }

                }

            }


            return population;


        }

由于这些方法,我的应用程序被卡住了......如果突变和交叉成功完成,我需要进入下一个迭代。

标签: c#arraylist

解决方案


不幸的是,在这种情况下,唯一真正的答案是将有问题的代码移动到一个单独的线程中,这样主线程仍然可以用来抽取消息队列。

确保它不能被触发两次,确保在它运行时没有其他东西可以写入数据,并且即使在任何其他线程中读取任何数据(例如,显示中间结果)也要非常小心。


推荐阅读