Skip to content

Commit 76db353

Browse files
committed
updated hotelling
1 parent 28d80c8 commit 76db353

File tree

2 files changed

+31
-42
lines changed

2 files changed

+31
-42
lines changed

examples/hotelling_law/hotelling_law/agents.py

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
import random
33

44
import numpy as np
5-
from mesa import Agent
65

6+
from mesa.experimental.cell_space import CellAgent
77

8-
class StoreAgent(Agent):
8+
9+
class StoreAgent(CellAgent):
910
"""An agent representing a store with a price and ability to move
1011
and adjust prices."""
1112

@@ -22,10 +23,8 @@ def __init__(self, model, price=10, can_move=True, strategy="Budget"):
2223
# / differential (Premium)
2324

2425
def estimate_market_share(self, new_position=None):
25-
position = new_position if new_position else self.pos
26-
nearby_consumers = self.model.grid.get_neighborhood(
27-
position, moore=True, include_center=False, radius=8
28-
)
26+
position = new_position if new_position else self.cell
27+
nearby_consumers = position.get_neighborhood(radius=8).agents
2928

3029
# Filter nearby agents to include only ConsumerAgents.
3130
nearby_consumers = [
@@ -45,24 +44,23 @@ def move(self):
4544
if not self.can_move:
4645
return
4746

48-
best_position = self.pos
47+
best_position = self.cell
4948
best_market_share = self.estimate_market_share()
5049

51-
for neighbor in self.model.grid.get_neighborhood(
52-
self.pos, moore=True, include_center=False
53-
):
50+
for neighbor in self.cell.neighborhood:
5451
potential_market_share = self.estimate_market_share(new_position=neighbor)
5552
if potential_market_share >= best_market_share:
5653
best_market_share = potential_market_share
5754
best_position = neighbor
58-
self.model.grid.move_agent(self, best_position)
55+
56+
self.cell = best_position
5957

6058
def adjust_price(self):
6159
# Calculate competitor prices and the average competitor price
6260
competitor_prices = [
6361
store.price
64-
for store in self.model.get_store_agents()
65-
if store.unique_id != self.unique_id
62+
for store in self.model.agents_by_type[StoreAgent]
63+
if store is not self
6664
]
6765
average_competitor_price = (
6866
np.mean(competitor_prices) if competitor_prices else self.price
@@ -71,7 +69,7 @@ def adjust_price(self):
7169
# Calculate the current and average market share
7270
current_market_share = self.market_share
7371
all_market_shares = [
74-
store.market_share for store in self.model.get_store_agents()
72+
store.market_share for store in self.model.agents_by_type[StoreAgent]
7573
]
7674
average_market_share = np.mean(all_market_shares) if all_market_shares else 0
7775

@@ -119,8 +117,8 @@ def adjust_price(self):
119117

120118
def identify_competitors(self):
121119
competitors = []
122-
for agent in self.model.agents:
123-
if isinstance(agent, StoreAgent) and agent.unique_id != self.unique_id:
120+
for agent in self.model.agents_by_type[StoreAgent]:
121+
if agent is not self:
124122
# Estimate market overlap as a measure of competition
125123
overlap = self.estimate_market_overlap(agent)
126124
if overlap > 0: # If there's any market overlap,
@@ -133,7 +131,7 @@ def estimate_market_overlap(self, other_store):
133131
This could be based on shared consumer base or other factors."""
134132
overlap = 0
135133

136-
for consumer in self.model.get_consumer_agents():
134+
for consumer in self.model.agents_by_type[ConsumerAgent]:
137135
preferred_store = consumer.determine_preferred_store()
138136
if preferred_store in (self, other_store):
139137
overlap += 1
@@ -156,7 +154,7 @@ def step(self):
156154
self.adjust_price()
157155

158156

159-
class ConsumerAgent(Agent):
157+
class ConsumerAgent(CellAgent):
160158
"""A consumer agent that chooses a store
161159
based on price and distance."""
162160

@@ -165,8 +163,8 @@ def __init__(self, model):
165163
self.preferred_store = None
166164

167165
def determine_preferred_store(self):
168-
consumer_preference = self.model.consumer_preferences
169-
stores = self.model.get_store_agents()
166+
consumer_preference = self.model.agents_by_type[ConsumerAgent]
167+
stores = self.model.agents_by_type[StoreAgent]
170168

171169
if len(stores) == 0: # Check if the stores AgentSet is empty
172170
return None
@@ -177,11 +175,11 @@ def determine_preferred_store(self):
177175
for store in stores:
178176
# Calculate score based on consumer preference
179177
if consumer_preference == "proximity":
180-
score = self.euclidean_distance(self.pos, store.pos)
178+
score = self.euclidean_distance(self.cell.coordinate, store.cell.coordinate)
181179
elif consumer_preference == "price":
182180
score = store.price
183181
else: # Default case includes both proximity and price
184-
score = store.price + self.euclidean_distance(self.pos, store.pos)
182+
score = store.price + self.euclidean_distance(self.cell.coordinate, store.cell.coordinate)
185183

186184
# Update the list of best stores if a new minimum score is found
187185
if score < min_score:

examples/hotelling_law/hotelling_law/model.py

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from mesa import Model
55
from mesa.agent import AgentSet
66
from mesa.datacollection import DataCollector
7-
from mesa.space import MultiGrid
7+
from mesa.experimental.cell_space import OrthogonalMooreGrid
88

99
from .agents import ConsumerAgent, StoreAgent
1010

@@ -99,12 +99,12 @@ def __init__(
9999

100100
# Initialize the spatial grid based on the specified environment type.
101101
if environment_type == "grid":
102-
self.grid = MultiGrid(
103-
width, height, True
102+
self.grid = OrthogonalMooreGrid(
103+
(width, height), True
104104
) # A grid where multiple agents can occupy the same cell.
105105
elif environment_type == "line":
106-
self.grid = MultiGrid(
107-
1, height, True
106+
self.grid = OrthogonalMooreGrid(
107+
(1, height), True
108108
) # A grid representing a line (single occupancy per cell).
109109

110110
self._initialize_agents()
@@ -186,29 +186,20 @@ def _initialize_agents(self):
186186

187187
agent = StoreAgent(self, can_move=can_move, strategy=strategy)
188188

189-
self.store_agents.add(agent)
190-
191189
# Randomly place agents on the grid for a grid environment.
192-
x = self.random.randrange(self.grid.width)
193-
y = self.random.randrange(self.grid.height)
194-
self.grid.place_agent(agent, (x, y))
190+
x = self.random.randrange(self.grid.dimensions[0])
191+
y = self.random.randrange(self.grid.dimensions[1])
192+
agent.cell = self.grid[(x,y)]
195193

196194
# Place consumer agents
197195
for _ in range(self.num_consumers):
198196
# Ensure unique ID across all agents
199197
consumer = ConsumerAgent(self)
200198

201-
self.consumer_agents.add(consumer)
202199
# Place consumer randomly on the grid
203-
x = self.random.randrange(self.grid.width)
204-
y = self.random.randrange(self.grid.height)
205-
self.grid.place_agent(consumer, (x, y))
206-
207-
def get_store_agents(self):
208-
return self.store_agents
209-
210-
def get_consumer_agents(self):
211-
return self.consumer_agents
200+
x = self.random.randrange(self.grid.dimensions[0])
201+
y = self.random.randrange(self.grid.dimensions[1])
202+
consumer.cell = self.grid[(x,y)]
212203

213204
# Method to advance the simulation by one step.
214205
def step(self):

0 commit comments

Comments
 (0)