Issue
So I am trying to simulate an animal hunting and resting. When the animal rests it can either digest or stay the same based on probabilities. When the animal is hunting it can either hunt successfully or not or stay the same based on probabilities. I want the outer nested loop to be the number of animals and the inner loop be the lifespan. The animals has a lower gut limit when the animal is resting if it reaches that level it automatically starts to hunt. The animal also has an upper gut level during hunting and when it reaches it it rests. In addition if the animal reaches a negative state it breaks out of the loop and continues on to the next animal.
I am am trying to run the nested loop and I do not understand what is wrong! Please help me! I noticed when I printed the alist and I looked at the states, there would be weird jumps from like: [0,4,i ] to [1,2,i] and it just skipped over the belly being 4-1! So I want to start of with an initial state then append the list as conditions are met then, I tried to say if the belly reaches a negative I want to record that state then break out and start all over with the next animal .
I also need to count the number of times the animal was successful at hunting, not successful at hunting, times the belly digested, and the number of times the animal stayed the same. I haven't gotten this far yet
Thank you in advance! Sorry if it is confusing! I am not that great at python Here is my code:
import random
initial_state=[0,4,0]#means it is resting, at full belly of 4 these two values also vary
alist=[initial_state]
died=0
u,s=2,4 #u is the lower belly limit, s is the upper belly limit
a,b,d=1/8,1/3,1/2 #a is the probability for not catching food, b is the probability for getting food,d is the probability for digestion these values also vary
for i in range (100000):
digest=random.random()
hunts=random.random()
for i in range(1,501):#each animal has a 500 lifespan
digest=random.random()
hunts=random.random()
if alist[i-1][1]==-1:
died+=1
break #the animal died
if alist[i-1][0]==0:#If the animal is resting
if digest<=d:
belly=alist[i-1][1]-1
if belly <= u:
alist.append([1,belly,i])
else:
alist.append([0,belly,i])
if digest>1-d:#the animal remains the same
belly=alist[i-1][1]
alist.append([0,belly,i])
if alist[i-1][0]==1:#if the animal is hunting
if alist[i-1][1]>=1:
if hunts<=a:
belly=alist[i-1][1]-1
alist.append([1,belly,i])
if a<hunts<=a+b:
belly=alist[i-1][1]+1
if belly==s:#if the animal has a full belly it rests
alist.append([0,belly,i])
else:
alist.append([1,belly,i])
if hunts>a+b:
belly=alist[i-1][1]
alist.append([alist[i-1][0],belly,i])
elif alist[i-1][1]==0:#When the belly is empty while hunting
if hunts<=a:
belly=alist[i-1][1]-1
alist.append([0,belly,i])
if a<hunts<=a+b:
belly=alist[i-1][1]+1
alist.append([1,belly,i])
if hunts>a+b:
belly=alist[i-1][1]
alist.append([alist[i-1][0],belly,i])
Heading
Solution
I refactored your code massively. Changes include:
- renaming everything so that we can see more clearly what variables actually represent.
- getting rid of
alist[i-1]
since we are always looking at the previous state,-1
index is sufficient. - checking for belly and hunt states as high as possible to avoid redundant mentions of
alist
. - not storing
i
anymore because if we want it we can just useenumerate
. - fixed the probabilities (you had too many checks, and
a + b != 1
when you defineda
andb
were the probability of not catching and catching food respectively.
Tested a few times, I did not notice the jump in belly level that you mentionned in the comments.
# Imports.
import random
# Constants.
ANIMALS = 3
ANIMAL_LIFESPAN = 30
BELLY_EMPTY = 2 # Will always trigger a hunt next cycle.
BELLY_FULL = 4 # Will always trigger a rest next cycle.
FOOD_CATCHING_PROBABILITY = 1/3
DIGESTION_PROBABILITY = 1/2
INITIAL_STATE = (False, BELLY_FULL) # The animal starts in resting position with a full belly.
# Run the simulation.
animals_states = {} # I use a dict here to save myself some `append`s.
death_counter = 0
for n in range(ANIMALS):
states = animals_states[n] = [INITIAL_STATE]
for _ in range(ANIMAL_LIFESPAN):
# Grab previous states.
is_hunting, belly = states[-1]
if is_hunting:
if random.random() <= FOOD_CATCHING_PROBABILITY:
belly += 1
hunt_next = False if belly == BELLY_FULL else True # Full belly is triggering a rest on the next cycle.
else:
belly -= 1
hunt_next = True
else: # If the animal is resting.
if random.random() <= DIGESTION_PROBABILITY:
belly -= 1
hunt_next = True if belly <= BELLY_EMPTY else False # Empty belly is triggering a hunt on the next cycle.
else: # The animal remains the same.
hunt_next = False
states.append((hunt_next, belly))
# The animal starved.
if belly == 0:
death_counter += 1
break
# For testing purpose.
for n, states in animals_states.items():
print(f"\nAnimal {n} states:")
for is_hunting, belly in states:
print(is_hunting, belly)
Output:
Animal 0 states:
False 4
False 4
False 3
True 2
True 1
True 2
True 1
True 0
Animal 1 states:
False 4
False 4
False 4
False 3
False 3
True 2
True 1
True 2
True 1
True 0
Animal 2 states:
False 4
False 4
False 3
True 2
True 1
True 0
True 1
True 0
Answered By - Guimoute Answer Checked By - Willingham (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.