英文:
Modelling a Sheep vs Rabbit population simulation (Python)
问题
我试图模拟羊和兔的种群,使用以下规则:
- 如果两种不同物种的动物在nside方格上的同一个方块上相遇,有可能它们都不死、都死亡,或者其中一个死亡。
- 如果同种物种的动物在一个方块上相遇,就有机会(概率类似于上面的情况)产生一个新的幼崽。
在下一个时间步中,存活的动物可以向左、向右、向上或向下移动。
我的问题是,在我的模型中,两种物种都在呈指数增长,我不确定如何解决这个问题。
我尝试过的方法是检查每一对动物。如果这对动物不包含死亡的动物,然后使用if-else条件来评估它们是否应该诞生新的动物或死亡。请注意,我的代码中的nsides代表网格的大小。我还将我的动物类命名为People2,因为它是从以前的代码中改编的。
# 测试不同的if/else函数
import numpy as np
class People2: # 动物类
def __init__(self, status, species, nsides=40):
self.nsides = nsides
self.location = np.random.randint(0, self.nsides, [2])
self.status = status
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.rabbits = []
self.sheep = []
self.time = 0
self.maxtime = 1000
for i in range(self.npeople):
if i % 2 == 0:
self.rabbits.append(People2(status=1, species='R', nsides=nsides)) # 生病的兔子
else:
self.sheep.append(People2(status=1, species='S', nsides=nsides)) # 健康的羊
self.people = self.rabbits + self.sheep
def movement(self):
self.to_remove = []
self.compare = []
new = []
# 伪代码
self.a_list2 = list(enumerate(self.people))
self.anim_combined = list(itertools.combinations(self.a_list2, 2))
for r, s in self.anim_combined:
if r[1].status != 0 and s[1].status != 0:
if np.all(r[1].location == s[1].location):
if r[1].species != s[1].species:
r_prob, s_prob = np.random.choice([0, 1], p=[self.nprob, 1 - self.nprob], size=2)
if r_prob == 1:
pass
else:
r[1].status = 0
if s_prob == 1:
pass
else:
s[1].status = 0
else:
if r[1].species == s[1].species:
repro_prob = np.random.choice([1, 0], p=[self.nprob, 1 - self.nprob])
if repro_prob == 0:
pass
else:
if repro_prob == 1:
new.append(People2(status=1, species=r[1].species, nsides=self.nsides))
unique_elements = list(itertools.chain.from_iterable(self.anim_combined))
not_killed = [index_and_animal[1] for index_and_animal in unique_elements if index_and_animal[1].status == 1]
self.people.extend(new)
self.people.extend(list(set(not_killed)))
self.time += 1
for animal in self.people:
animal.move()
return self.people
# 迭代4天
anim_world = World2()
rabbit_len = []
sheep_len = []
for _ in range(4):
rabbit_count = 0
sheep_count = 0
for animal in anim_world.movement():
if animal.species == "R":
rabbit_count += 1
elif animal.species == "S":
sheep_count += 1
rabbit_len.append(rabbit_count)
sheep_len.append(sheep_count)
如果我能看到它们为什么呈指数增长以及为什么一些不同物种的动物没有被杀死,那将非常好。提前感谢您!
英文:
I am trying to model a sheep vs rabbit population with the following rules:
- If two animals of different species meet on the same square on an nside grid, there is a chance that either none, both or one of them die.
- If animals with the same species meet on a square, there is a chance (similar probability as ^^) that a new baby will be born.
In the next time step, the live animals can move either left, right, up or down.
My problem is that in my model, both species are exponentially growing and I'm not sure how to fix this.
What I have tried:
My approach to solving this problem was examine each of the pairs.
If the pair doesn't contain a dead animal, then evaluate its status if a new animal should be born or dead using if else conditions. Note that nsides in my code represents the size of the grid. I've also called my animal class People2 as it was adapted from a previous code.
#testing the different if/else functions
import numpy as np
class People2: #class animals
def __init__(self, status, species, nsides=40): #change here
self.nsides = nsides
self.location = np.random.randint(0, self.nsides, [2])
self.status = status
self.species=species
def move(self): #moving animals up or down
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.rabbits=[]
self.sheep=[]
#self.people = []
#who_is_sick = np.random.randint(0, self.npeople)
self.time=0
self.maxtime=1000
for i in range(self.npeople):
if i%2 == 0:
self.rabbits.append(People2(status=1, species='R', nsides=nsides)) # sick person
else:
self.sheep.append(People2(status=1, species='S' , nsides=nsides)) # healthy person
self.people=self.rabbits+self.sheep
def movement(self):
self.to_remove=[]
self.compare=[]
new=[]
#pseudocode
self.a_list2=list(enumerate(self.people))
self.anim_combined=list(itertools.combinations(self.a_list2, 2))
#traverse through list, if I am not my self:
for r, s in self.anim_combined: #note that r,s don't refer to rabits vs sheep, could be anyanimal
if r[1].status!=0 and s[1].status!=0:
if np.all(r[1].location==s[1].location):
if (r[1].species!=s[1].species) : #diff species
r_prob, s_prob = np.random.choice([0, 1],p=[self.nprob,1-self.nprob], size=2)
if r_prob==1:
pass
else:
r[1].status==0
if s_prob==1:
pass
else:
s[1].status==0
else: #same species
if (r[1].species==s[1].species):
repro_prob=np.random.choice([1, 0], p=[self.nprob,1-self.nprob] )
if repro_prob==0:
pass
else: #if the prob is 1, then append a "baby"
if repro_prob==1:
new.append(People2(status=1, species=r[1].species, nsides=self.nsides))
#remove those who are dead (i.e. status=0)
unique_elements = list(itertools.chain.from_iterable(self.anim_combined))
not_killed = [index_and_animal[1] for index_and_animal in unique_elements if index_and_animal[1].status == 1]
# putting all the alive animals back into the original equation
self.people.extend(new) #adding the new babies
self.people.extend(list(set(not_killed))) #adding whatever wasn't killed into this list
self.time += 1
for animal in self.people:
animal.move()
return self.people
#iterating over 4 days
anim_world = World2()
rabbit_len = []
sheep_len = []
for _ in range(4): #iterating for 10 days
rabbit_count = 0
sheep_count = 0
for animal in anim_world.movement():
if animal.species == "R":
rabbit_count += 1
elif animal.species == "S":
sheep_count += 1
rabbit_len.append(rabbit_count)
sheep_len.append(sheep_count)
If I could see why they are exponentially growing and why some animals arent being killed if they are of different species,that would be great. Thanks in advance!
答案1
得分: 0
你正在复制所有存活的动物,使用self.people.extend(list(set(not_killed)))
。尝试将self.people.extend(new)
替换为self.people = new
。这将使它成为所有新的动物,而不是扩展仍然存活的那些。你也可以将self.people
设置为空数组,例如:
self.people = []
self.people.extend(new)
self.people.extend(list(set(not_killed)))
或者你可以将self.people
设置为list(set(not_killed))
,例如:
self.people = list(set(not_killed))
self.people.extend(new)
但无论如何,在扩展之前,你确实需要设置self.people
,否则在设置时会删除已扩展的部分。
希望这有所帮助!
P.S. slothrop 是对的,你可能想将r[1].status==0
替换为r[1].status=0
。
英文:
You are duplicating all the living animals with self.people.extend(list(set(not_killed)))
. try replacing self.people.extend(new)
with self.people = new
. That will set it to be all the new ones than you extend all the ones that are still alive. You could alternatively set self.people
to a empty array e.g.
self.people = []
self.people.extend(new)
self.people.extend(list(set(not_killed)))
or you can set self.people
to list(set(not_killed))
e.g.
self.people=list(set(not_killed))
self.people.extend(new)
You do need to set self.people
before you extend it though. otherwise you would remove the extended ones when it is set.
Hope this helps!
P.S. slothrop is right you probably want to replace r[1].status==0
with r[1].status=0
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论