遗传算法之匹配字符串(python实现)

文章详细描述了一种遗传算法,通过随机生成字符串、计算适应度、交叉和变异操作,逐步逼近目标字符串。通过种群大小、变异率和迭代代数的设置,展示了解决字符串匹配问题的进化搜索策略。
摘要由CSDN通过智能技术生成

        首先先附上代码的全部内容再对代码进行一一解析

import random
import string

# 目标字符串
target_string = "HELLO, WORLD!"

# 参数设置
population_size = 500
mutation_rate = 0.3
generations = 11000

def generate_random_string(length):
    return ''.join(random.choice(string.printable) for _ in range(length))

def calculate_fitness(individual):
    return sum(1 for a, b in zip(individual, target_string) if a == b)

def crossover(parent1, parent2):
    # 一点交叉
    crossover_point = random.randint(0, len(parent1) - 1)
    child = parent1[:crossover_point] + parent2[crossover_point:]
    return child

def mutate(individual):
    # 随机选择一个位置进行变异
    mutation_point = random.randint(0, len(individual) - 1)
    mutated_char = random.choice(string.printable)
    return individual[:mutation_point] + mutated_char + individual[mutation_point + 1:]

def genetic_algorithm():
    # 初始化种群
    population = [generate_random_string(len(target_string)) for _ in range(population_size)]

    for generation in range(generations):
        # 计算适应度
        fitness_scores = [calculate_fitness(individual) for individual in population]

        # 找到当前最优解
        best_individual = population[fitness_scores.index(max(fitness_scores))]
        print(f"Generation {generation + 1}: {best_individual} (Fitness: {max(fitness_scores)})")

        # 如果找到完美解决方案,退出循环
        if max(fitness_scores) == len(target_string):
            break

        # 选择父代
        selected_parents = random.choices(population, weights=fitness_scores, k=2)

        # 交叉产生新个体
        child = crossover(selected_parents[0], selected_parents[1])

        # 变异
        if random.random() < mutation_rate:
            child = mutate(child)

        # 替换旧个体
        population[random.randint(0, population_size - 1)] = child

        # 打印每一步的种群
        print("Population:", population)

    print("Algorithm finished.")
    print("Best solution:", best_individual)

# 运行遗传算法
genetic_algorithm()

运行结果

参数设置

# 参数设置
population_size = 500
mutation_rate = 0.3
generations = 11000
  1. 种群大小 (population_size):

    种群大小是指每一代中包含的个体数量。在这个遗传算法中,种群大小被设置为 500。较大的种群大小通常能够更好地覆盖搜索空间,但也需要更多的计算资源。这个值的选择应根据问题的复杂性和可用的计算资源来确定。
  2. 变异率 (mutation_rate):

    变异率表示在交叉操作后,每个个体发生变异的概率。在这里,变异率被设置为 0.3,即30%的概率。较高的变异率可以帮助算法跳出局部最优解,但过高的变异率可能导致搜索过于随机。这个值的选择取决于对搜索过程的探索程度的期望。
  3. 迭代的代数 (generations):

    代数数表示算法将运行的总次数。在这个例子中,迭代的代数被设置为 11000。这个值的选择通常需要考虑算法运行的时间和是否能在给定的代数内找到满足条件的解。如果在指定的代数内找到了满足条件的解,算法将提前结束。

生产随机字符函数

def generate_random_string(length):
    return ''.join(random.choice(string.printable) for _ in range(length)
  1. random.choice(string.printable):

    • random.choice 函数用于从给定的可迭代对象中随机选择一个元素。
    • 在这里,string.printable 是一个包含所有可打印ASCII字符的字符串,包括数字、字母、标点符号和空格。
    • 因此,random.choice(string.printable) 会在这些字符中随机选择一个字符。
  2. for _ in range(length):

    • 使用 for 循环迭代 range(length),生成指定长度的字符。
  3. ''.join(...):

    • join 方法用于将可迭代对象的元素连接成一个字符串。
    • 在这里,将 random.choice(string.printable) 在循环中生成的字符连接成一个字符串。
  4. return ...:

    • 返回由随机选择的字符组成的字符串。

因此,这个函数的作用是生成一个具有指定长度的随机字符串,该字符串的字符来自于所有可打印ASCII字符

适应度函数

def calculate_fitness(individual):
    return sum(1 for a, b in zip(individual, target_string) if a == b)

  1. zip(individual, target_string):

    • zip 函数接受两个可迭代对象,将它们的元素逐一配对。在这里,它将 individualtarget_string 中的字符一一配对,生成一个迭代器。
    • 例如,如果 individual 是 "ABC",而 target_string 是 "ADE",那么 zip 将生成迭代器: ('A', 'A'), ('B', 'D'), ('C', 'E')
  2. (1 for a, b in ...):

    • 这是一个生成器表达式。它遍历 zip 生成的配对,对于每一对 (a, b),生成一个值为 1 的元素。
    • 如果在对应的位置上 individualtarget_string 中的字符相等,则生成的值是 1,否则是 0
  3. if a == b:

    • 过滤条件。只有在 individualtarget_string 中的字符相等时才生成 1
  4. sum(...):

    • sum 函数对生成器表达式生成的值进行求和,即计算匹配的字符数量。

所以,整个语句的含义是:对于两个字符串 individualtarget_string 中相应位置上相等的字符,计算它们的数量。进而用于遗传算法中的适应度计算。下面通过具体例子说明代码

        假设目标字符串是 "HELLO, WORLD!",而个体字符串是 "HELLO, PEOPLE!"

zip(individual, target_string)

  • 对应位置的字符配对为:('H', 'H'), ('E', 'E'), ('L', 'L'), ('L', 'L'), ('O', 'O'), (',', ','), (' ', ' '), ('W', 'W'), ('O', 'O'), ('R', 'R'), ('L', 'L'), ('D', 'D'), ('!', '!')

(1 for a, b in ...)

  • 由于个体字符和目标字符在每个位置上都匹配,生成的元素为 1

sum(...)

  • 对生成的 1 进行求和,得到总和:1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 = 13

return sum(1 for a, b in zip(individual, target_string) if a == b)

  • 返回适应度分数 13

交叉函数

def crossover(parent1, parent2):
    # 一点交叉
    crossover_point = random.randint(0, len(parent1) - 1)
    child = parent1[:crossover_point] + parent2[crossover_point:]
    return child
  1. rossover_point = random.randint(0, len(parent1) - 1):

    • 随机选择一个交叉点,这个点将决定在哪里进行交叉。它在父代个体的基因序列中的位置。
  2. child = parent1[:crossover_point] + parent2[crossover_point:]:

    • parent1[:crossover_point]parent1 的基因序列的开头到交叉点之前的部分。
    • parent2[crossover_point:]parent2 的基因序列从交叉点开始到末尾的部分。
    • 这两部分被连接起来,形成了新个体(子代)的基因序列。
  3. return child:

    • 返回表示子代的基因序列。

        这个交叉过程模拟了生物遗传中的杂交过程,其中从两个父代中选择某个点,然后将其前半部分与后半部分组合以产生新个体,其实就是拼凑了两个个体中的一部分。这有助于保留父代中较好的特征,并且在不同个体之间引入差异性。 

变异函数 

def mutate(individual):
    # 随机选择一个位置进行变异
    mutation_point = random.randint(0, len(individual) - 1)
    mutated_char = random.choice(string.printable)
    return individual[:mutation_point] + mutated_char + individual[mutation_point + 1:]

 

  1. random.randint(0, len(individual) - 1):

    • random.randintrandom 模块中的函数,用于生成指定范围内的随机整数。
    • 这里它生成一个在 0 和 len(individual) - 1 之间的随机整数,即变异点的位置。
  2. random.choice(string.printable):

    • random.choice 函数用于从给定的可迭代对象中随机选择一个元素。
    • 在这里,它从 string.printable 中随机选择一个字符。这个字符串包含了所有可打印ASCII字符。
  3. mutated_char = random.choice(string.printable):

    • 选择的随机字符用于代替变异点处的原始字符。
  4. individual[:mutation_point] + mutated_char + individual[mutation_point + 1:]:

    • 切片操作被用来构建一个新的基因序列。
    • individual[:mutation_point] 返回变异点之前的部分。
    • mutated_char 是变异点处的新字符。
    • individual[mutation_point + 1:] 返回变异点之后的部分。
    • 这三部分被连接起来形成一个新的基因序列,即发生了变异的个体。
  5. return individual[:mutation_point] + mutated_char + individual[mutation_point + 1:]:

    • 返回表示发生变异的个体的新基因序列。

这个函数通过在基因序列中的一个随机位置引入变异,用新的随机字符替代原始字符。

遗传算法函数

def genetic_algorithm():
    # 初始化种群
    population = [generate_random_string(len(target_string)) for _ in range(population_size)]

    for generation in range(generations):
        # 计算适应度
        fitness_scores = [calculate_fitness(individual) for individual in population]

        # 找到当前最优解
        best_individual = population[fitness_scores.index(max(fitness_scores))]
        print(f"Generation {generation + 1}: {best_individual} (Fitness: {max(fitness_scores)})")

        # 如果找到完美解决方案,退出循环
        if max(fitness_scores) == len(target_string):
            break

        # 选择父代
        selected_parents = random.choices(population, weights=fitness_scores, k=2)

        # 交叉产生新个体
        child = crossover(selected_parents[0], selected_parents[1])

        # 变异
        if random.random() < mutation_rate:
            child = mutate(child)

        # 替换旧个体
        population[random.randint(0, population_size - 1)] = child

        # 打印每一步的种群
        print("Population:", population)

    print("Algorithm finished.")
    print("Best solution:", best_individual)
  1. population = [generate_random_string(len(target_string)) for _ in range(population_size)]:

    使用列表推导式初始化一个由随机字符串组成的种群。每个字符串的长度与目标字符串相同。
  2. for generation in range(generations)::

    外部循环,迭代代数。
  3. fitness_scores = [calculate_fitness(individual) for individual in population]:

    计算每个个体的适应度分数,将结果存储在列表 fitness_scores 中。
  4. best_individual = population[fitness_scores.index(max(fitness_scores))]:

    找到当前代种群中适应度最高的个体。
  5. print(f"Generation {generation + 1}: {best_individual} (Fitness: {max(fitness_scores)})"):

    打印当前代数、最佳个体及其适应度分数。
  6. if max(fitness_scores) == len(target_string)::

    如果找到完美解决方案,退出循环。
  7. selected_parents = random.choices(population, weights=fitness_scores, k=2):

    选择两个父代个体,概率权重与它们的适应度分数成正比。
  8. child = crossover(selected_parents[0], selected_parents[1]):

    通过交叉操作产生一个新的子代。
  9. if random.random() < mutation_rate::

    根据变异率的概率决定是否进行变异。
  10. child = mutate(child):

    如果进行变异,对子代进行变异操作。
  11. population[random.randint(0, population_size - 1)] = child:

    用新的子代替换原种群中的一个个体。
  • 25
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值