Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix deterministic behavior in move_agent_to_one_of with selection="closest" #2118

Merged
merged 5 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions mesa/space.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,15 +459,21 @@ def move_agent_to_one_of(
elif selection == "closest":
current_pos = agent.pos
# Find the closest position without sorting all positions
closest_pos = None
# TODO: See if this method can be optimized further
closest_pos = []
min_distance = float("inf")
agent.random.shuffle(pos)
for p in pos:
EwoutH marked this conversation as resolved.
Show resolved Hide resolved
EwoutH marked this conversation as resolved.
Show resolved Hide resolved
distance = self._distance_squared(p, current_pos)
if distance < min_distance:
min_distance = distance
closest_pos = p
chosen_pos = closest_pos
closest_pos.clear()
closest_pos.append(p)
elif distance == min_distance:
closest_pos.append(p)

chosen_pos = agent.random.choice(closest_pos)

else:
raise ValueError(
f"Invalid selection method {selection}. Choose 'random' or 'closest'."
Expand Down
17 changes: 17 additions & 0 deletions tests/test_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,23 @@ def test_move_agent_closest_selection(self):
self.space.move_agent_to_one_of(agent, possible_positions, selection="closest")
assert agent.pos == (6, 6)

def test_move_agent_closest_selection_multiple(self):
random_locations = []
agent = self.agents[0]
agent.pos = (5, 5)
repetititions = 10

for _ in range(repetititions):
possible_positions = [(4, 4), (6, 6), (10, 10), (20, 20)]
self.space.move_agent_to_one_of(
agent, possible_positions, selection="closest"
)
random_locations.append(agent.pos)
assert agent.pos in possible_positions
self.space.move_agent_to_one_of(agent, [(5, 5)], selection="closest")
non_random_locations = [random_locations[0]] * repetititions
assert random_locations != non_random_locations

def test_move_agent_invalid_selection(self):
agent = self.agents[0]
possible_positions = [(10, 10), (20, 20), (30, 30)]
Expand Down
Loading