I am trying to model a sheep vs rabbit population with the following rules:
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!
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
.