Source code for experimental.continuous_space.continuous_space_agents
"""Continuous space agents."""
from __future__ import annotations
from itertools import compress
from typing import Protocol
import numpy as np
from mesa.agent import Agent
from mesa.experimental.continuous_space import ContinuousSpace
[docs]
class HasPositionProtocol(Protocol):
"""Protocol for continuous space position holders."""
position: np.ndarray
[docs]
class ContinuousSpaceAgent(Agent):
"""A continuous space agent.
Attributes:
space (ContinuousSpace): the continuous space in which the agent is located
position (np.ndarray): the position of the agent
"""
__slots__ = ["_mesa_index", "space"]
@property
def position(self) -> np.ndarray:
"""Position of the agent."""
return self.space.agent_positions[self.space._agent_to_index[self]]
@position.setter
def position(self, value: np.ndarray) -> None:
if not self.space.in_bounds(value):
if self.space.torus:
value = self.space.torus_correct(value)
else:
raise ValueError(f"point {value} is outside the bounds of the space")
self.space.agent_positions[self.space._agent_to_index[self]] = value
@property
def pos(self): # noqa: D102
# just here for compatibility with solara_viz.
return self.position
@pos.setter
def pos(self, value):
# just here for compatibility solara_viz.
pass
def __init__(self, space: ContinuousSpace, model):
"""Initialize a continuous space agent.
Args:
space: the continuous space in which the agent is located
model: the model to which the agent belongs
"""
super().__init__(model)
self.space: ContinuousSpace = space
self.space._add_agent(self)
# self.position[:] = np.nan
[docs]
def remove(self) -> None:
"""Remove and delete the agent from the model and continuous space."""
super().remove()
self.space._remove_agent(self)
self._mesa_index = None
self.space = None
[docs]
def get_neighbors_in_radius(
self, radius: float | int = 1
) -> tuple[list, np.ndarray]:
"""Get neighbors within radius.
Args:
radius: radius within which to look for neighbors
"""
agents, dists = self.space.get_agents_in_radius(self.position, radius=radius)
logical = np.asarray([agent is not self for agent in agents])
agents = list(compress(agents, logical))
return agents, dists[logical]
[docs]
def get_nearest_neighbors(self, k: int = 1) -> tuple[list, np.ndarray]:
"""Get neighbors within radius.
Args:
k: the number of nearest neighbors to return
"""
# return includes self, so we need to get k+1
agents, dists = self.space.get_k_nearest_agents(self.position, k=k + 1)
logical = np.asarray([agent is not self for agent in agents])
agents = list(compress(agents, logical))
return agents, dists[logical]