遗传算法——无序变长染色体的交叉策略咨询
嘿,针对你开发的这款带有无序、可变长度且允许重复染色体的遗传算法,我整理了一些Python实现的关键思路和代码示例,帮你搞定核心环节:
核心需求回顾
- 染色体为无序结构:个体内染色体的排列顺序不影响适应度得分
- 染色体长度不固定:个体的染色体数量从1条到100+不等
- 允许染色体重复存在
- 用Python实现,染色体以列表形式存储
简化版个体示例
# 示例个体Ea(含重复染色体) individual_ea = ["gene_Alpha", "gene_Beta", "gene_Alpha", "gene_Gamma"] # 示例个体Eb(仅1条染色体) individual_eb = ["gene_Delta"]
关键实现要点
1. 适应度计算(核心:忽略顺序,关注组成与数量)
因为染色体无序,计算适应度时要完全抛开列表顺序,只统计基因的类型和出现次数。可以用collections.Counter来快速处理:
from collections import Counter def calculate_fitness(individual): # 统计每个基因的出现次数 gene_counts = Counter(individual) # 示例:根据基因权重计算适应度(可根据你的业务逻辑调整) fitness = gene_counts.get("gene_Alpha", 0) * 2 + gene_counts.get("gene_Gamma", 0) * 3 return fitness
2. 选择操作(无需特殊调整,复用经典策略)
常规的选择方法(轮盘赌、锦标赛选择等)依然适用,只要确保传入的是基于基因组成计算出的正确适应度值即可,不需要因为染色体的无序/可变长度做额外修改。
3. 交叉操作(难点:设计不依赖顺序的融合逻辑)
针对无序+可变长度的特点,推荐两种实用的交叉策略:
随机子集交叉
从两个父代中按随机比例选取基因(允许重复),直接合并成子代:
import random def crossover(parent1, parent2): # 随机分配从两个父代取基因的比例(避免极端比例) take_ratio_p1 = random.uniform(0.3, 0.7) take_ratio_p2 = 1 - take_ratio_p1 # 从父代中随机采样对应数量的基因(允许重复采样) child_part1 = random.choices(parent1, k=int(len(parent1)*take_ratio_p1)) child_part2 = random.choices(parent2, k=int(len(parent2)*take_ratio_p2)) # 合并得到子代 return child_part1 + child_part2
基因计数融合
先统计两个父代的基因出现次数,按比例融合计数后,再生成子代列表:
def crossover_by_count(parent1, parent2): count_p1 = Counter(parent1) count_p2 = Counter(parent2) child_counts = {} # 融合两个父代的基因计数(按50%比例示例) for gene in set(count_p1.keys()).union(count_p2.keys()): count_p1_val = count_p1.get(gene, 0) count_p2_val = count_p2.get(gene, 0) child_counts[gene] = int((count_p1_val + count_p2_val) * 0.5) # 根据计数生成子代列表 child = [] for gene, cnt in child_counts.items(): child.extend([gene]*cnt) # 确保子代至少有1条染色体 return child if child else [random.choice(list(count_p1.keys()) + list(count_p2.keys()))]
4. 变异操作(适配可变长度特性)
设计三种变异类型,覆盖替换、添加、删除场景:
def mutate(individual, gene_pool): mutation_type = random.choice(["replace", "add", "delete"]) if mutation_type == "replace" and len(individual) > 0: # 随机替换一个基因 idx = random.randint(0, len(individual)-1) individual[idx] = random.choice(gene_pool) elif mutation_type == "add": # 随机添加一个新基因 individual.append(random.choice(gene_pool)) elif mutation_type == "delete" and len(individual) > 1: # 随机删除一个基因(保证个体至少有1条染色体) idx = random.randint(0, len(individual)-1) del individual[idx] return individual
内容的提问来源于stack exchange,提问作者Wayne Workman




