88 Center for Connected Learning and Computer-Based Modeling,
99 Northwestern University, Evanston, IL.
1010"""
11+ import math
1112
12- import mesa
13+ from mesa import Model , Agent
1314from mesa .space import MultiGrid
1415from mesa .time import RandomActivationByType
1516
16- from .agents import GrassPatch , Sheep , Wolf
1717
18+ class Animal (Agent ):
1819
19- class WolfSheep (mesa .Model ):
20+ def __init__ (self , unique_id , model , moore , energy , p_reproduce , energy_from_food ):
21+ super ().__init__ (unique_id , model )
22+ self .energy = energy
23+ self .p_reproduce = p_reproduce
24+ self .energy_from_food = energy_from_food
25+ self .moore = moore
26+
27+ def random_move (self ):
28+ next_moves = self .model .grid .get_neighborhood (self .pos , self .moore , True )
29+ next_move = self .random .choice (next_moves )
30+ # Now move:
31+ self .model .grid .move_agent (self , next_move )
32+
33+ def spawn_offspring (self ):
34+ self .energy /= 2
35+ offspring = self .__class__ (
36+ self .model .next_id (), self .model , self .moore , self .energy , self .p_reproduce , self .energy_from_food
37+ )
38+ self .model .grid .place_agent (offspring , self .pos )
39+ self .model .schedule .add (offspring )
40+
41+ def feed (self ):
42+ ...
43+
44+ def die (self ):
45+ self .model .grid .remove_agent (self )
46+ self .remove ()
47+
48+ def step (self ):
49+ self .random_move ()
50+ self .energy -= 1
51+
52+ self .feed ()
53+
54+ if self .energy < 0 :
55+ self .die ()
56+ elif self .random .random () < self .p_reproduce :
57+ self .spawn_offspring ()
58+
59+
60+ class Sheep (Animal ):
61+ """
62+ A sheep that walks around, reproduces (asexually) and gets eaten.
63+
64+ The init is the same as the RandomWalker.
65+ """
66+
67+ def feed (self ):
68+ # If there is grass available, eat it
69+ agents = self .model .grid .get_cell_list_contents (self .pos )
70+ grass_patch = next (obj for obj in agents if isinstance (obj , GrassPatch ))
71+ if grass_patch .fully_grown :
72+ self .energy += self .energy_from_food
73+ grass_patch .fully_grown = False
74+
75+ class Wolf (Animal ):
76+ """
77+ A wolf that walks around, reproduces (asexually) and eats sheep.
78+ """
79+
80+ def feed (self ):
81+ agents = self .model .grid .get_cell_list_contents (self .pos )
82+ sheep = [obj for obj in agents if isinstance (obj , Sheep )]
83+ if len (sheep ) > 0 :
84+ sheep_to_eat = self .random .choice (sheep )
85+ self .energy += self .energy
86+
87+ # Kill the sheep
88+ sheep_to_eat .die ()
89+
90+
91+ class GrassPatch (Agent ):
92+ """
93+ A patch of grass that grows at a fixed rate and it is eaten by sheep
94+ """
95+
96+ def __init__ (self , unique_id , model , fully_grown , countdown ):
97+ """
98+ Creates a new patch of grass
99+
100+ Args:
101+ grown: (boolean) Whether the patch of grass is fully grown or not
102+ countdown: Time for the patch of grass to be fully grown again
103+ """
104+ super ().__init__ (unique_id , model )
105+ self .fully_grown = fully_grown
106+ self .countdown = countdown
107+
108+ def step (self ):
109+ if not self .fully_grown :
110+ if self .countdown <= 0 :
111+ # Set as fully grown
112+ self .fully_grown = True
113+ self .countdown = self .model .grass_regrowth_time
114+ else :
115+ self .countdown -= 1
116+
117+
118+ class WolfSheep (Model ):
20119 """
21120 Wolf-Sheep Predation Model
22121
23122 A model for simulating wolf and sheep (predator-prey) ecosystem modelling.
24123 """
25124
26125 def __init__ (
27- self ,
28- seed ,
29- height ,
30- width ,
31- initial_sheep ,
32- initial_wolves ,
33- sheep_reproduce ,
34- wolf_reproduce ,
35- grass_regrowth_time ,
36- wolf_gain_from_food = 13 ,
37- sheep_gain_from_food = 5 ,
126+ self ,
127+ seed ,
128+ height ,
129+ width ,
130+ initial_sheep ,
131+ initial_wolves ,
132+ sheep_reproduce ,
133+ wolf_reproduce ,
134+ grass_regrowth_time ,
135+ wolf_gain_from_food = 13 ,
136+ sheep_gain_from_food = 5 ,
137+ moore = False
38138 ):
39139 """
40140 Create a new Wolf-Sheep model with the given parameters.
@@ -49,41 +149,37 @@ def __init__(
49149 grass_regrowth_time: How long it takes for a grass patch to regrow
50150 once it is eaten
51151 sheep_gain_from_food: Energy sheep gain from grass, if enabled.
152+ moore:
52153 """
53154 super ().__init__ (seed = seed )
54155 # Set parameters
55156 self .height = height
56157 self .width = width
57158 self .initial_sheep = initial_sheep
58159 self .initial_wolves = initial_wolves
59- self .sheep_reproduce = sheep_reproduce
60- self .wolf_reproduce = wolf_reproduce
61- self .wolf_gain_from_food = wolf_gain_from_food
62160 self .grass_regrowth_time = grass_regrowth_time
63- self .sheep_gain_from_food = sheep_gain_from_food
64161
65162 self .schedule = RandomActivationByType (self )
66163 self .grid = MultiGrid (self .height , self .width , torus = False )
67164
68- # Create sheep:
69- for _i in range (self .initial_sheep ):
165+ for _ in range (self .initial_sheep ):
70166 pos = (
71167 self .random .randrange (self .width ),
72168 self .random .randrange (self .height ),
73169 )
74- energy = self .random .randrange (2 * self . sheep_gain_from_food )
75- sheep = Sheep (self .next_id (), pos , self , True , energy )
170+ energy = self .random .randrange (2 * sheep_gain_from_food )
171+ sheep = Sheep (self .next_id (), self , moore , energy , sheep_reproduce , sheep_gain_from_food )
76172 self .grid .place_agent (sheep , pos )
77173 self .schedule .add (sheep )
78174
79175 # Create wolves
80- for _i in range (self .initial_wolves ):
176+ for _ in range (self .initial_wolves ):
81177 pos = (
82178 self .random .randrange (self .width ),
83179 self .random .randrange (self .height ),
84180 )
85- energy = self .random .randrange (2 * self . wolf_gain_from_food )
86- wolf = Wolf (self .next_id (), pos , self , True , energy )
181+ energy = self .random .randrange (2 * wolf_gain_from_food )
182+ wolf = Wolf (self .next_id (), self , moore , energy , wolf_reproduce , wolf_gain_from_food )
87183 self .grid .place_agent (wolf , pos )
88184 self .schedule .add (wolf )
89185
@@ -95,9 +191,20 @@ def __init__(
95191 countdown = self .grass_regrowth_time
96192 else :
97193 countdown = self .random .randrange (self .grass_regrowth_time )
98- patch = GrassPatch (self .next_id (), pos , self , fully_grown , countdown )
194+ patch = GrassPatch (self .next_id (), self , fully_grown , countdown )
99195 self .grid .place_agent (patch , pos )
100196 self .schedule .add (patch )
101197
102198 def step (self ):
103199 self .schedule .step ()
200+
201+
202+ if __name__ == "__main__" :
203+ import time
204+
205+ model = WolfSheep (15 , 25 , 25 , 60 , 40 , 0.2 , 0.1 , 20 )
206+
207+ start_time = time .perf_counter ()
208+ for _ in range (100 ):
209+ model .step ()
210+ print ("Time:" , time .perf_counter () - start_time )
0 commit comments