如何实现低适应度Board优先的带偏随机选择及选中记录功能?
嘿,这两个需求都很好实现,我给你拆解一下:
一、实现偏向低fitness值的随机选择
你想用random()加阈值的思路是对的,更简洁的方式是基于权重的随机选择——给fitness越低的board分配越高的选中权重。Python的random.choices()原生支持权重参数,非常适合这个场景。
因为你的population是heapq(本质是列表),每个元素是(fitness, board),我们可以直接提取fitness计算权重:
import random def weighted_random_selection(population): # 拆分fitness和board列表 fitnesses, boards = zip(*population) # 计算权重:fitness越低,权重越高(+1避免fitness为0时除零错误) weights = [1 / (fit + 1) for fit in fitnesses] # 按权重随机选1个board return random.choices(boards, weights=weights, k=1)[0]
举个例子,你提到的(1, board1)和(7, board2),它们的权重分别是1/2和1/8,board1的选中概率是board2的4倍,完美符合你要的偏向性。
如果你想要更强的线性偏向(比如fitness=1的概率是fitness=7的7倍),可以换成线性反向权重:
max_fitness = max(fit for fit, _ in population) weights = [max_fitness - fit + 1 for fit in fitnesses]
二、跟踪已选中的board
因为所有board都是唯一的,我们可以用集合来记录选中历史(集合自动去重,查询效率高)。最好把选择逻辑和跟踪逻辑封装成类,避免全局变量的混乱:
import random class BoardSelectionTracker: def __init__(self): # 用集合存储已选中的board(要求board是可哈希类型,比如元组、自定义哈希对象) self.selected_boards = set() def weighted_select(self, population): fitnesses, boards = zip(*population) weights = [1 / (fit + 1) for fit in fitnesses] selected_board = random.choices(boards, weights=weights, k=1)[0] # 记录选中的board self.selected_boards.add(selected_board) return selected_board def get_selected_history(self): # 返回副本,避免外部修改内部集合 return self.selected_boards.copy()
使用起来很简单:
# 初始化跟踪器 tracker = BoardSelectionTracker() # 多次选择 selected = tracker.weighted_select(population) # 查看历史选中记录 print(tracker.get_selected_history())
如果你的board是不可哈希的类型(比如列表),可以把它转换成可哈希的形式(比如tuple(board))再存入集合,或者给自定义的board类实现__hash__和__eq__方法。
额外说明
你的population是heapq堆结构,但这不影响我们的权重计算——因为堆只是维护了元素的顺序,我们依然可以遍历所有元素来计算每个board的权重,完全不冲突。
内容的提问来源于stack exchange,提问作者Joshua
相关产品推荐
相关产品推荐

