Skip to content

Commit 7131bdd

Browse files
authored
Fix deterministic behavior in move_agent_to_one_of with selection="closest" (#2118)
This PR addresses a bug in `move_agent_to_one_of` where agents exhibit deterministic behavior when multiple closest positions are available and `selection="closest"` is used.
1 parent cd852c8 commit 7131bdd

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

mesa/space.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,15 +459,21 @@ def move_agent_to_one_of(
459459
elif selection == "closest":
460460
current_pos = agent.pos
461461
# Find the closest position without sorting all positions
462-
closest_pos = None
462+
# TODO: See if this method can be optimized further
463+
closest_pos = []
463464
min_distance = float("inf")
464465
agent.random.shuffle(pos)
465466
for p in pos:
466467
distance = self._distance_squared(p, current_pos)
467468
if distance < min_distance:
468469
min_distance = distance
469-
closest_pos = p
470-
chosen_pos = closest_pos
470+
closest_pos.clear()
471+
closest_pos.append(p)
472+
elif distance == min_distance:
473+
closest_pos.append(p)
474+
475+
chosen_pos = agent.random.choice(closest_pos)
476+
471477
else:
472478
raise ValueError(
473479
f"Invalid selection method {selection}. Choose 'random' or 'closest'."

tests/test_space.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,23 @@ def test_move_agent_closest_selection(self):
509509
self.space.move_agent_to_one_of(agent, possible_positions, selection="closest")
510510
assert agent.pos == (6, 6)
511511

512+
def test_move_agent_closest_selection_multiple(self):
513+
random_locations = []
514+
agent = self.agents[0]
515+
agent.pos = (5, 5)
516+
repetititions = 10
517+
518+
for _ in range(repetititions):
519+
possible_positions = [(4, 4), (6, 6), (10, 10), (20, 20)]
520+
self.space.move_agent_to_one_of(
521+
agent, possible_positions, selection="closest"
522+
)
523+
random_locations.append(agent.pos)
524+
assert agent.pos in possible_positions
525+
self.space.move_agent_to_one_of(agent, [(5, 5)], selection="closest")
526+
non_random_locations = [random_locations[0]] * repetititions
527+
assert random_locations != non_random_locations
528+
512529
def test_move_agent_invalid_selection(self):
513530
agent = self.agents[0]
514531
possible_positions = [(10, 10), (20, 20), (30, 30)]

0 commit comments

Comments
 (0)