我正在尝试在c#中实现遗传算法。遗传方法有交叉法和变异法。种群大小为5条染色体,其中每条染色体是2d整数数组(矩阵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;
}
我的应用因为这些方法而陷入困境...... 如果成功完成突变和交叉,我需要进入下一次迭代。
答案 0 :(得分:1)
不幸的是,在这种情况下唯一真正的答案是将违规代码移动到一个单独的线程中,这样主线程仍可用于抽取消息队列。
确保无法触发两次,确保在数据运行时没有其他任何内容可以写入数据并且非常警惕甚至读取任何数据(对于例如,在任何其他线程中显示中间结果。