You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python实现带偏置无重复列表抽样(TSP遗传算法场景)

针对你在TSP遗传算法里的种群筛选需求——要从按适应度排序后的种群里淘汰一半,同时让高适应度个体有更高存活概率,我给你几个实用的解决方案,能完美避开你之前遇到的重复选择问题:

方案1:无放回轮盘赌选择

这个方法的核心是每次选中个体后就从候选池中移除,彻底避免重复选择。因为你的种群已经按路径长度(适应度)从高到低排好序,我们可以直接用路径距离的倒数作为权重(距离越短,权重越大,存活概率越高),也可以用排名相关的权重。

import random

def select_survivors(population, survival_rate=0.5):
    # 复制原种群,避免修改原始数据
    candidate_pool = population.copy()
    survivors = []
    num_survive = int(len(population) * survival_rate)
    
    for _ in range(num_survive):
        # 计算权重:用路径距离的倒数,保证短路径(高适应度)权重更高
        weights = [1 / path[1][0] for path in candidate_pool]
        # 随机选择1个个体
        selected = random.choices(candidate_pool, weights=weights, k=1)[0]
        survivors.append(selected)
        # 从候选池移除已选个体,防止重复
        candidate_pool.remove(selected)
    
    return survivors

如果你的种群规模很大,用列表的remove()方法效率偏低,你可以改用索引操作来优化:

import random

def select_survivors(population, survival_rate=0.5):
    num_individuals = len(population)
    num_survive = int(num_individuals * survival_rate)
    # 生成所有个体的索引
    candidate_indices = list(range(num_individuals))
    survivors = []
    
    for _ in range(num_survive):
        # 根据索引获取对应的距离,计算权重
        weights = [1 / population[i][1][0] for i in candidate_indices]
        # 选择一个索引
        selected_idx = random.choices(candidate_indices, weights=weights, k=1)[0]
        survivors.append(population[selected_idx])
        # 移除已选索引
        candidate_indices.remove(selected_idx)
    
    return survivors
方案2:基于排名的numpy无放回抽样

numpy的np.random.choice()支持无放回抽样(设置replace=False),刚好解决你之前遇到的重复问题。因为你的种群已经按适应度排序,我们可以直接给每个个体分配和排名挂钩的权重——排名越靠前(适应度越高),权重越大,这样存活概率自然更高。

import numpy as np

def select_survivors(population, survival_rate=0.5):
    num_individuals = len(population)
    num_survive = int(num_individuals * survival_rate)
    
    # 生成排名权重:第1名(索引0)权重为num_individuals,第2名为num_individuals-1,依此类推
    rank_weights = np.arange(num_individuals, 0, -1)
    # 归一化权重(numpy不强制要求总和为1,但归一化后更直观)
    normalized_weights = rank_weights / rank_weights.sum()
    
    # 无放回选择指定数量的索引
    selected_indices = np.random.choice(num_individuals, size=num_survive, replace=False, p=normalized_weights)
    # 根据索引提取存活个体
    survivors = [population[i] for i in selected_indices]
    
    return survivors

如果你想让高适应度个体的存活概率提升更明显,可以把权重改成非线性的,比如平方权重:

rank_weights = np.arange(num_individuals, 0, -1) ** 2
normalized_weights = rank_weights / rank_weights.sum()

这样前几名个体的权重占比会大幅提升,存活概率更高。

方案3:带偏置的锦标赛选择

锦标赛选择是遗传算法里常用的选择策略,你可以给高适应度个体更高的入选锦标赛的概率,或者直接利用已排序的种群特性,让前N个个体有更高的被选中概率:

import random

def select_survivors(population, survival_rate=0.5, tournament_size=3):
    num_individuals = len(population)
    num_survive = int(num_individuals * survival_rate)
    survivors = []
    
    for _ in range(num_survive):
        # 给前半部分个体更高的入选概率(比如2倍权重)
        weights = [2 if i < num_individuals//2 else 1 for i in range(num_individuals)]
        # 随机选择锦标赛选手
        tournament_candidates = random.choices(population, weights=weights, k=tournament_size)
        # 选择锦标赛里适应度最高的(路径最短的)
        tournament_candidates.sort(key=lambda x: x[1][0])
        survivors.append(tournament_candidates[0])
    
    return survivors

这个方法的优势是实现简单,而且能保证高适应度个体更容易被选中,同时也能引入一定的随机性。


内容的提问来源于stack exchange,提问作者Sergey Ronin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:08:02