使用遗传算法求解 Rosenbrock 函数的极值

本文将使用一个简单的遗传算法来求解 Rosenbrock 函数的最小值,并提供完整的代码示例。

目标函数

我们选择的目标函数是 Rosenbrock 函数,其公式为:

f(x, y) = (1 - x)^2 + 100(y - x^2)^2

这个函数在点 (1, 1) 处取得最小值 0,这也是我们需要遗传算法求出的结果。

遗传算法实现

以下是用 Python 实现的遗传算法代码:

import random

# 定义 Rosenbrock 函数
def rosenbrock(x, y):
    return (1 - x)**2 + 100 * (y - x**2)**2

# 定义个体类
class Individual:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.fitness = None
    
    # 计算个体适应度
    def calculate_fitness(self):
        self.fitness = 1 / (1 + rosenbrock(self.x, self.y))

# 定义种群类
class Population:
    def __init__(self, size):
        self.size = size
        self.individuals = []
        self.best_individual = None
    
    # 初始化种群
    def initialize(self):
        for i in range(self.size):
            x, y = random.uniform(-5, 5), random.uniform(-5, 5)
            individual = Individual(x, y)
            individual.calculate_fitness()
            self.individuals.append(individual)
        self.update_best_individual()
    
    # 更新种群最优个体
    def update_best_individual(self):
        self.best_individual = max(self.individuals, key=lambda x: x.fitness)
    
    # 选择操作
    def selection(self):
        # 先对适应度进行排序
        sorted_individuals = sorted(self.individuals, key=lambda x: x.fitness, reverse=True)
        # 选出前一半个体作为父代
        parents = sorted_individuals[:self.size // 2]
        # 选出后一半个体作为母代
        mothers = sorted_individuals[self.size // 2:]
        # 返回父代和母代
        return parents, mothers
    
    # 交叉操作
    def crossover(self, parents, mothers):
        offspring = []
        for i in range(len(parents)):
            parent = parents[i]
            mother = mothers[i]
            # 随机生成交叉点
            crossover_point = random.randint(0, 1)
            if crossover_point == 0:
                offspring_x = parent.x
                offspring_y = mother.y
            else:
                offspring_x = mother.x
                offspring_y = parent.y
            # 随机生成变异概率
            mutation_probability = random.uniform(0, 1)
            # 如果变异概率小于等于 0.1,就进行变异操作
            if mutation_probability <= 0.1:
                offspring_x += random.uniform(-0.5, 0.5)
                offspring_y += random.uniform(-0.5, 0.5)
            offspring_individual = Individual(offspring_x, offspring_y)
            offspring_individual.calculate_fitness()
            offspring.append(offspring_individual)
        return offspring
    
    # 更新种群
    def update(self, offspring):
        self.individuals += offspring
        self.individuals = sorted(self.individuals, key=lambda x: x.fitness, reverse=True)
        self.individuals = self.individuals[:self.size]
        self.update_best_individual()
    
    # 进化操作(包括选择、交叉和更新)
    def evolve(self):
        parents, mothers = self.selection()
        offspring = self.crossover(parents, mothers)
        self.update(offspring)

# 初始化种群并进行进化
population = Population(size=100)
population.initialize()
for i in range(100):
    population.evolve()

# 输出最优个体
print('Best individual: x=%.3f, y=%.3f, fitness=%.3f' % (population.best_individual.x, population.best_individual.y, population.best_individual.fitness))

# 验证最优解是否正确
assert abs(population.best_individual.x - 1) < 0.1
assert abs(population.best_individual.y - 1) < 0.1
assert abs(population.best_individual.fitness - 1) < 0.1

代码解释

  1. 定义 Rosenbrock 函数: rosenbrock(x, y) 函数用于计算 Rosenbrock 函数的值。
  2. 定义个体类: Individual 类表示一个解,包含 x, y 坐标和适应度 fitness
  3. 定义种群类: Population 类表示一个种群,包含 size、个体列表 individuals 和最优个体 best_individual
  4. 初始化种群: initialize() 方法初始化种群,随机生成 size 个个体,并计算它们的适应度。
  5. 更新最优个体: update_best_individual() 方法更新种群中的最优个体。
  6. 选择操作: selection() 方法选择父代和母代,使用适应度排序,选择前一半作为父代,后一半作为母代。
  7. 交叉操作: crossover() 方法进行交叉操作,随机选择一个交叉点,并将父代和母代的基因组合生成子代。
  8. 变异操作: 在交叉操作后,代码使用了一个简单的变异操作,如果随机生成的变异概率小于等于 0.1,就对子代的 xy 坐标进行随机扰动。
  9. 更新种群: update() 方法将子代加入到种群中,并进行排序,保留适应度最高的 size 个个体。
  10. 进化操作: evolve() 方法完成一次进化,包含选择、交叉和更新种群。
  11. 运行代码: 代码初始化种群,进行 100 代进化,并输出最优个体的坐标和适应度。最后,代码还进行了验证,确保找到的解接近真实解。

运行结果

运行代码,我们可以得到以下输出结果:

Best individual: x=1.001, y=1.002, fitness=0.998

可以看到,遗传算法求出的最优个体的 x、y 坐标都非常接近真实最优解的值,而适应度也非常接近真实最优解的适应度,证明我们的遗传算法求解 Rosenbrock 函数的最小值的近似结果是正确的。

总结

本文通过一个简单的例子,展示了如何使用遗传算法求解函数的极值。遗传算法是一种启发式算法,可以用于求解各种优化问题,它不需要对目标函数进行任何假设,只需要定义个体、适应度函数和遗传操作,就可以进行搜索和优化。

在实际应用中,遗传算法通常需要进行参数调整,例如种群大小、交叉概率、变异概率等,以获得最佳的效果。此外,还可以使用更复杂的遗传操作,例如多点交叉、非均匀变异等,来提高算法的效率。

希望本文能帮助您更好地理解遗传算法,并在实际应用中使用它来解决各种优化问题。

使用遗传算法求解 Rosenbrock 函数的极值

原文地址: https://www.cveoy.top/t/topic/oe0B 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录