C#遗传算法:代码世界的 “进化传奇”

C#遗传算法:代码世界的 “进化传奇”

编码文章call10242025-02-01 3:31:5913A+A-

遗传算法:代码世界的 “进化传奇”

在神奇的大自然中,生物们为了适应环境,不断进化。遗传算法就像是把生物进化的这套 “生存秘籍” 偷学到了代码世界里。想象一下,代码也能像生物一样 “生孩子”“变异”,最后进化出解决复杂问题的超能力,是不是很神奇?

算法原理:代码版的 “生物进化”

遗传算法的核心思想来源于达尔文的进化论,简单来说就是 “物竞天择,适者生存”。在遗传算法里,我们把问题的每个可能解看作一个 “生物个体”,这些个体组成了一个 “种群”。

编码:给代码 “穿新衣”

首先,要把每个解(也就是个体)进行编码,就好比给生物穿上一件特别的 “衣服”,这件 “衣服” 上的信息代表了解的特征。最常见的编码方式是二进制编码,比如用一串 0 和 1 来表示一个个体。假如我们要求解一个简单的数学问题,比如找到一个在 0 到 15 之间的整数 x,使得 x 的平方最接近 100。我们可以用 4 位二进制数来编码 x,0000 表示 0,0001 表示 1,以此类推。

适应度函数:评判 “生存能力”

每个个体都有一个适应度,这就像是生物在自然界中的生存能力。适应度函数用来计算每个个体的适应度,对于刚才找最接近 100 的平方数问题,适应度函数可以是 100 减去 x 平方的绝对值,这个值越小,说明个体的适应度越高,也就是这个解越好。

选择:“强者生存”

接下来是选择阶段,就像大自然中强者生存一样,适应度高的个体有更大的概率被选中,进入下一代。常用的选择方法有轮盘赌选择法,把每个个体想象成轮盘上的一块区域,适应度越高,这块区域就越大,被选中的概率也就越大。

交叉:“生孩子”

被选中的个体要 “生孩子” 啦,这就是交叉操作。比如有两个个体 A(0011)和 B(1100),随机选择一个交叉点,假设是第 2 位,那么交叉后就产生两个新个体 A'(0000)和 B'(1111),这两个新个体就进入了下一代种群。

变异:“小调皮搞破坏”

变异就像是生物遗传过程中的小意外,偶尔会发生。在个体的编码中,随机改变某一位的值,比如把 0 变成 1,或者把 1 变成 0 。这可以给种群引入新的基因,防止算法陷入局部最优解。就像生物界偶尔出现的基因突变,可能会诞生出更适应环境的新物种。

不断重复选择、交叉和变异的过程,种群就会像生物一样不断进化,最后得到的最优个体,很可能就是我们要找的问题的最优解。

应用场景:遗传算法的 “七十二变”

旅行商问题

之前提到的旅行商要走遍多个城市,遗传算法可以把每条可能的路线看作一个个体,通过不断进化,找到最短的路线。就好像旅行商的后代们在不断尝试各种旅行计划,最后找到了最省时间和成本的那一条。

函数优化

在数学中,我们常常要找到一个函数的最大值或最小值。遗传算法把函数的自变量编码成个体,通过进化找到使函数值最优的自变量组合。比如找到一个复杂函数在某个区间内的最大值,遗传算法就像一个聪明的探险家,在这个区间里不断探索,找到那个最高点。

机器学习中的参数调优

在训练机器学习模型时,有很多参数需要调整,不同的参数组合会影响模型的性能。遗传算法可以把这些参数组合看作个体,通过进化找到最优的参数组合,让模型的性能达到最佳。就像给模型找到最合身的 “装备”,让它在预测任务中表现得更出色。

代码实现:让代码 “进化” 起来

下面是用 C# 实现遗传算法解决旅行商问题的简单示例:

using System;
using System.Collections.Generic;

using System.Linq;

class City

{

 public int X { get; set; }

 public int Y { get; set; }

 public City(int x, int y)

 {

 X = x;

 Y = y;

 }

}

class GeneticAlgorithm

{

 private List cities;

 private int populationSize;

 private double mutationRate;

 private int tournamentSize;

 private bool elitism;

 public GeneticAlgorithm(List cities, int populationSize, double mutationRate, int tournamentSize, bool elitism)

 {

 this.cities = cities;

 this.populationSize = populationSize;

 this.mutationRate = mutationRate;

 this.tournamentSize = tournamentSize;

 this.elitism = elitism;

 }

 // 生成初始种群

 public List> GenerateInitialPopulation()

 {

 List> population = new List>();

 for (int i = 0; i < populationSize; i++)

 {

 List route = Enumerable.Range(0, cities.Count).ToList();

 route = Shuffle(route);

 population.Add(route);

 }

 return population;

 }

 // 计算路线总距离

 public double CalculateDistance(List route)

 {

 double distance = 0;

 for (int i = 0; i < route.Count - 1; i++)

 {

 City city1 = cities[route[i]];

 City city2 = cities[route[i + 1]];

 distance += Math.Sqrt(Math.Pow(city2.X - city1.X, 2) + Math.Pow(city2.Y - city1.Y, 2));

 }

 City start = cities[route[0]];

 City end = cities[route[route.Count - 1]];

 distance += Math.Sqrt(Math.Pow(start.X - end.X, 2) + Math.Pow(start.Y - end.Y, 2));

 return distance;

 }

 // 计算种群中每个个体的适应度

 public List CalculateFitness(List> population)

 {

 List fitness = new List();

 foreach (var route in population)

 {

 double distance = CalculateDistance(route);

 fitness.Add(1 / distance);

 }

 return fitness;

 }

 // 轮盘赌选择

 public List RouletteWheelSelection(List> population, List fitness)

 {

 double totalFitness = fitness.Sum();

 double selectionPoint = new Random().NextDouble() * totalFitness;

 double runningTotal = 0;

 for (int i = 0; i < population.Count; i++)

 {

 runningTotal += fitness[i];

 if (runningTotal >= selectionPoint)

 {

 return population[i];

 }

 }

 return population[0];

 }

 // 锦标赛选择

 public List TournamentSelection(List> population, List fitness)

 {

 List tournament = new List();

 Random random = new Random();

 for (int i = 0; i < tournamentSize; i++)

 {

 int index = random.Next(0, populationSize);

 tournament.Add(index);

 }

 int bestIndex = tournament.OrderByDescending(i => fitness[i]).First();

 return population[bestIndex];

 }

 // 交叉操作

 public List Crossover(List parent1, List parent2)

 {

 int start = new Random().Next(0, parent1.Count);

 int end = new Random().Next(start, parent1.Count);

 List child = new List();

 for (int i = 0; i < parent1.Count; i++)

 {

 if (i >= start && i <= end)

 {

 child.Add(parent1[i]);

 }

 else

 {

 foreach (int city in parent2)

 {

 if (!child.Contains(city))

 {

 child.Add(city);

 break;

 }

 }

 }

 }

 return child;

 }

 // 变异操作

 public List Mutate(List route)

 {

 for (int i = 0; i < route.Count; i++)

 {

 if (new Random().NextDouble() < mutationRate)

 {

 int swapIndex = new Random().Next(0, route.Count);

 int temp = route[i];

 route[i] = route[swapIndex];

 route[swapIndex] = temp;

 }

 }

 return route;

 }

 // 进化种群

 public List> EvolvePopulation(List> population)

 {

 List> newPopulation = new List>();

 List fitness = CalculateFitness(population);

 if (elitism)

 {

 int bestIndex = fitness.IndexOf(fitness.Max());

 newPopulation.Add(population[bestIndex]);

 }

 while (newPopulation.Count < populationSize)

 {

 List parent1 = TournamentSelection(population, fitness);

 List parent2 = TournamentSelection(population, fitness);

 List child = Crossover(parent1, parent2);

 child = Mutate(child);

 newPopulation.Add(child);

 }

 return newPopulation;

 }

 // 打乱列表顺序

 private List Shuffle(List list)

 {

 Random random = new Random();

 for (int i = list.Count - 1; i > 0; i--)

 {

 int j = random.Next(0, i + 1);

 int temp = list[i];

 list[i] = list[j];

 list[j] = temp;

 }

 return list;

 }

}

class Program

{

 static void Main()

 {

 List cities = new List

 {

 new City(0, 0),

 new City(1, 1),

 new City(2, 4),

 new City(3, 2),

 new City(4, 3)

 };

 GeneticAlgorithm ga = new GeneticAlgorithm(cities, 100, 0.01, 5, true);

 List> population = ga.GenerateInitialPopulation();

 for (int i = 0; i < 1000; i++)

 {

 population = ga.EvolvePopulation(population);

 }

 List fitness = ga.CalculateFitness(population);

 int bestIndex = fitness.IndexOf(fitness.Max());

 List bestRoute = population[bestIndex];

 Console.WriteLine("最优路线:");

 foreach (int cityIndex in bestRoute)

 {

 Console.Write(cityIndex + " ");

 }

 Console.WriteLine();

 }

}


遗传算法就像一个神奇的 “进化工厂”,让代码在不断的 “繁衍” 和 “变异” 中,找到解决问题的最佳方案。要是你还想知道遗传算法在其他有趣场景中的应用,或者对代码有优化建议,欢迎随时和我聊。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4