Python羊兔种群模拟问题:指数增长及物种未正确死亡排查
羊(S)与兔(R)种群模拟模型问题修复
模型规则
- 不同物种的两只动物在
nsides网格的同一方格相遇时,存在无死亡、两者都死亡或其一死亡的概率 - 同一物种的两只动物在同一方格相遇时,有概率诞生新个体
- 下一时间步,存活动物可向上下左右移动(网格边界采用循环处理)
现存问题
- 两物种种群均呈无限制指数增长,未体现种间竞争的抑制作用
- 不同物种相遇时,部分动物未被正确标记为死亡
代码问题定位
- 死亡状态赋值错误:标记动物死亡时误用比较运算符
==,而非赋值运算符=,导致死亡状态从未被正确设置 - 种群更新逻辑错误:原代码将存活动物追加到旧的
self.people列表后,而非替换原列表,导致死亡动物仍保留在种群中,叠加新繁殖个体后必然指数增长 - 缺失依赖导入:使用
itertools.combinations但未导入itertools模块,运行会触发报错 - 重复处理风险:原逻辑中通过
set去重存活动物,但People2实例不可哈希,set(not_killed)会触发错误
修复后的完整代码
import numpy as np import itertools # 补充缺失的导入 class People2: # 动物类,保留原命名 def __init__(self, status, species, nsides=40): self.nsides = nsides self.location = np.random.randint(0, self.nsides, [2]) self.status = status # 1=存活,0=死亡 self.species = species def move(self): # 随机上下左右移动,循环边界 moves = np.random.randint(-1, 2, [2]) self.location[0] = (self.location[0] + moves[0]) % self.nsides self.location[1] = (self.location[1] + moves[1]) % self.nsides class World2: def __init__(self, time=0, maxtime=1000, nsides=40, npeople=2, nprob=0.9): self.npeople = npeople self.nprob = nprob # 死亡/繁殖概率参数 self.nsides = nsides self.time = time self.maxtime = maxtime # 初始化种群:交替生成兔(R)和羊(S) self.people = [] for i in range(self.npeople): species = 'R' if i % 2 == 0 else 'S' self.people.append(People2(status=1, species=species, nsides=nsides)) def step(self): # 重命名movement为step,更贴合模拟逻辑 new_individuals = [] # 生成所有存活动物的两两组合 alive_animals = [animal for animal in self.people if animal.status == 1] animal_pairs = itertools.combinations(alive_animals, 2) for a1, a2 in animal_pairs: # 仅处理同一位置的动物对 if np.all(a1.location == a2.location): if a1.species != a2.species: # 不同物种相遇:判断死亡概率 # nprob是存活概率,1-nprob是死亡概率 a1_survive = np.random.choice([True, False], p=[self.nprob, 1-self.nprob]) a2_survive = np.random.choice([True, False], p=[self.nprob, 1-self.nprob]) if not a1_survive: a1.status = 0 if not a2_survive: a2.status = 0 else: # 同一物种相遇:判断繁殖概率 reproduce = np.random.choice([True, False], p=[self.nprob, 1-self.nprob]) if reproduce: new_individuals.append(People2(status=1, species=a1.species, nsides=self.nsides)) # 更新种群:保留存活个体 + 添加新繁殖个体 self.people = [animal for animal in self.people if animal.status == 1] + new_individuals # 所有存活动物移动 for animal in self.people: animal.move() self.time += 1 return self.people # 模拟运行 anim_world = World2(npeople=10, nprob=0.7) # 调整初始种群和概率便于观察 rabbit_counts = [] sheep_counts = [] for _ in range(20): # 模拟20步 current_pop = anim_world.step() r_count = sum(1 for animal in current_pop if animal.species == 'R') s_count = sum(1 for animal in current_pop if animal.species == 'S') rabbit_counts.append(r_count) sheep_counts.append(s_count) print("兔种群数量变化:", rabbit_counts) print("羊种群数量变化:", sheep_counts)
修复说明
- 修正死亡状态赋值:将
r[1].status==0改为a1.status = 0,确保死亡状态被正确设置 - 重构种群更新逻辑:每次模拟步后,直接筛选存活个体并添加新繁殖个体,替换原
self.people列表,避免旧个体残留 - 补充
itertools导入,修复运行报错 - 优化动物对处理逻辑:先筛选存活动物再生成组合,减少无效计算
- 重命名
movement方法为step,更符合模拟步骤的语义 - 调整概率逻辑的可读性:用布尔值替代0/1,代码更直观
内容的提问来源于stack exchange,提问作者Sl30202
相关产品推荐
相关产品推荐

