如何随机改变二进制列表中的 5 个值?

How to randomly mutate 5 values in a binary list?

我正在编写一个遗传算法,其中我需要 select 二进制列表 genotype 中的 5 个数字并翻转它们,所以 10 01。我尝试将我的代码放入带有 range(1,6) 的循环中,但是当我这样做时它仍然只更改其中一个数字。下面是我没有循环的原始代码,它随机 selects 一个二进制值并对其进行变异。除了列表中的 5 个元素之外,还有谁知道更好的方法吗?

genotype = [1,0,0,1,0,0,1,1,1,0]

def mutate(self):
  gene = random.choice(genotype)
  if genotype[gene] == 1:
    genotype[gene] = 0
  else:
    genotype[gene] = 1
  return genotype

您可以使用random.sample()函数从列表中获取5个唯一索引,然后循环翻转它们。像那样:

import random
genotype = [1,0,0,1,0,0,1,1,1,0]

random_five = random.sample(range(len(genotype)), 5)
for i in random_five:
    genotype[i] = 0 if genotype[i] == 1 else 1

print(genotype)

输出为:

[1, 1, 0, 1, 1, 0, 0, 1, 0, 1]

random.choice(genotype) 将 return 来自 基因型列表的随机元素 ,即,它将等于 0 或 1。所以,既然你是使用 gene 作为索引,您的函数将始终翻转索引 0 或索引 1 处的元素。

您可以改用 random.sample(population, k) 函数。

虽然在 给出的答案后您的主要问题似乎已解决:

for i in random.sample(range(len(genotype)), 5):
    genotype[i] ^= 1

并建议使用这种替代(更现实的)突变模型:

for i in [random.choice(range(len(genotype))) for _ in range(5)]:
    genotype[i] ^= 1

我发现这个观察非常具有挑战性并且有点鼓舞人心

I tried putting my code in a loop with a range(1,6) however when I do this it still only changes one of the numbers.

这总是正确的吗?可以还是必须?

我试了几次下面的代码(我从你原来的代码中删除了多余的self

import random
genotype = [1,0,0,1,0,0,1,1,1,0]

def mutate():
  gene = random.choice(genotype)
  if genotype[gene] == 1:
    genotype[gene] = 0
  else:
    genotype[gene] = 1
  return genotype

print(genotype)

for _ in range(1,6):
    mutate()

print(genotype)

并且只观察到这些输出:

  1. [0, 0, 0, 1, 0, 0, 1, 1, 1, 0] -- 索引 0 处的基因翻转
  2. [1, 1, 0, 1, 0, 0, 1, 1, 1, 0] -- 索引 1 处的基因翻转

事实上,必须这样才能对上面的mutate函数进行奇数次调用

因为 gene01 之一,并且同一基因上的两次翻转会重现初始值,因此只会保留与选择的基因索引相对应的突变奇数次,因为你调用它是为了range(1, 6)(奇数总数),所以在整个过程中,01中只有一个可以是奇数。

你的问题更多是针对软件工程的问题,而不是EA方面的问题。但是,我想对您从基因组中选择 5 个基因的设计决策提出一些建议。您正在限制 EA 探索对您的解决方案的搜索 space,并且您的 EA 肯定会陷入局部最优并且可能无法逃脱,因为突变的解决方案将仅围绕 5 个基因发生变化(如果限制来自本身就是一个问题,对此无能为力)。例如,EA 可能会通过仅更改 3 个基因或更改 7 个基因来找到接近最优的解决方案。如果是设计选择,您可能会考虑重新审视您的 EA 设计决策。

一般来说,EA社区使用的是基因变异概率。当一个人想要对后代进行变异时,它基于超参数变异概率(另外,由于这是超参数,您也可以针对您的问题调整它以在以后获得良好的结果)。

假设您改变 5 个基因的设计决策是一个约束,并且您还想使用可调超参数突变概率。您可以使用如下解决方案:

import random

def mutate(genotype, m_probe):
  mutated_offspring = []
  mutated_genes_indexes = set()
  for index, gene in enumerate(genotype):
    if random.uniform(0, 1) >= m_probe and len(mutated_genes_indexes) < 5:
      mutated_offspring.append(int(not gene))
      mutated_genes_indexes.add(index)
    else:
      mutated_offspring.append(int(gene))
  print("Mutated genes indexes: ", mutated_genes_indexes)
  return mutated_offspring

# Each genes have 20% probability to get mutated! NOTE: with higher probability you might not find 5 genes mutated, 20 is chosen based on the constraint and can be tuned later with this constraint.
genotype = [1,0,0,1,0,0,1,1,1,0]
print(mutate(genotype, 0.20))

我的首选设计决策是让所有基因无限制地发生突变的机会均等。在这种情况下,解决方案可能如下所示:

import random

def mutate(genotype, m_probe):
  mutated_offspring = []
  mutated_genes_indexes = set()
  for index, gene in enumerate(genotype):
    if random.uniform(0, 1) >= m_probe:
      mutated_offspring.append(int(not gene))
      mutated_genes_indexes.add(index)
    else:
      mutated_offspring.append(int(gene))
  print("Mutated genes indexes: ", mutated_genes_indexes)
  return mutated_offspring

genotype = [1,0,0,1,0,0,1,1,1,0]
print(mutate(genotype, 0.50))