CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-mesa

Agent-based modeling (ABM) in Python framework with spatial grids, agent schedulers, data collection tools, and browser-based visualization capabilities

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

spatial.mddocs/

Spatial Systems

Mesa provides two comprehensive spatial modeling approaches: the traditional mesa.space module (in maintenance mode) and the modern mesa.discrete_space module (under active development). Both systems enable positioning agents in space and managing spatial relationships, but with different design philosophies and capabilities.

Imports

# Traditional spatial system (maintenance mode)
from mesa.space import (
    MultiGrid, SingleGrid, HexSingleGrid, HexMultiGrid, 
    ContinuousSpace, NetworkGrid, PropertyLayer
)

# Modern discrete spatial system (active development)  
from mesa.discrete_space import (
    Grid, HexGrid, Network, VoronoiGrid,
    OrthogonalMooreGrid, OrthogonalVonNeumannGrid,
    Cell, CellAgent, FixedAgent, Grid2DMovingAgent, CellCollection,
    PropertyLayer, DiscreteSpace
)

# Type definitions
from typing import Tuple, List, Union, Optional, Iterable
import numpy as np

# Spatial coordinate types
Coordinate = tuple[int, int]
FloatCoordinate = tuple[float, float] | np.ndarray
NetworkCoordinate = int
Position = Coordinate | FloatCoordinate | NetworkCoordinate
GridContent = Agent | None
MultiGridContent = list[Agent]

Traditional Spatial System (mesa.space)

The traditional spatial system provides well-established grid and space classes that have been the foundation of Mesa models. These classes are now in maintenance mode with new development focused on mesa.discrete_space.

Grid Classes

SingleGrid

Grid where each cell contains at most one agent.

from mesa.space import SingleGrid

class SingleGrid:
    """
    Grid where each cell contains at most one agent.
    
    Provides basic grid functionality with unique occupancy constraint.
    """
    
    def __init__(self, width: int, height: int, torus: bool = False):
        """
        Initialize a SingleGrid.
        
        Parameters:
            width: Grid width in cells
            height: Grid height in cells  
            torus: Whether the grid wraps around at edges
        """
        ...
    
    def place_agent(self, agent, pos: Coordinate):
        """
        Place an agent at a specific position.
        
        Parameters:
            agent: Agent to place
            pos: (x, y) coordinate tuple
        """
        ...
    
    def move_agent(self, agent, pos: Coordinate):
        """
        Move an agent to a new position.
        
        Parameters:
            agent: Agent to move
            pos: New (x, y) coordinate tuple
        """
        ...
    
    def remove_agent(self, agent):
        """Remove an agent from the grid."""
        ...
    
    def get_cell_list_contents(self, cell_list: List[Coordinate]) -> List[Agent]:
        """Get all agents in specified cells."""
        ...
    
    def get_neighbors(self, pos: Coordinate, moore: bool = True, 
                     include_center: bool = False, radius: int = 1) -> List[Coordinate]:
        """
        Get neighboring positions.
        
        Parameters:
            pos: Center position
            moore: If True, use Moore neighborhood (8-connected), else Von Neumann (4-connected)
            include_center: Whether to include the center position
            radius: Neighborhood radius
        """
        ...
    
    def get_neighborhood(self, pos: Coordinate, moore: bool = True,
                        include_center: bool = False, radius: int = 1) -> List[Coordinate]:
        """Get neighborhood positions (alias for get_neighbors)."""
        ...
    
    def iter_neighbors(self, pos: Coordinate, moore: bool = True,
                      include_center: bool = False, radius: int = 1) -> Iterator[Agent]:
        """Iterate over agents in neighboring cells."""
        ...
    
    def find_empty(self) -> Coordinate | None:
        """Find a random empty cell, or None if grid is full."""
        ...
    
    def exists_empty_cells(self) -> bool:
        """Check if any empty cells exist."""
        ...

MultiGrid

Grid where each cell can contain multiple agents.

from mesa.space import MultiGrid

class MultiGrid:
    """
    Grid where each cell can contain multiple agents.
    
    Extends SingleGrid functionality to support multiple agents per cell.
    """
    
    def __init__(self, width: int, height: int, torus: bool = False):
        """
        Initialize a MultiGrid.
        
        Parameters:
            width: Grid width in cells
            height: Grid height in cells
            torus: Whether the grid wraps around at edges
        """
        ...
    
    def place_agent(self, agent, pos: Coordinate):
        """Add an agent to a cell (multiple agents allowed)."""
        ...
    
    def move_agent(self, agent, pos: Coordinate):
        """Move an agent to a new position."""
        ...
    
    def remove_agent(self, agent):
        """Remove an agent from the grid."""
        ...
    
    def get_cell_list_contents(self, cell_list: List[Coordinate]) -> List[Agent]:
        """Get all agents in specified cells."""
        ...
    
    # Inherits all SingleGrid methods with multi-agent behavior

Hexagonal Grids

HexSingleGrid and HexMultiGrid

Hexagonal grid variants providing 6-neighbor connectivity.

from mesa.space import HexSingleGrid, HexMultiGrid

class HexSingleGrid(SingleGrid):
    """Hexagonal grid with single agent per cell."""
    
    def get_neighbors(self, pos: Coordinate, include_center: bool = False, 
                     radius: int = 1) -> List[Coordinate]:
        """Get hexagonal neighbors (6-connected)."""
        ...

class HexMultiGrid(MultiGrid):
    """Hexagonal grid with multiple agents per cell."""
    
    def get_neighbors(self, pos: Coordinate, include_center: bool = False,
                     radius: int = 1) -> List[Coordinate]:
        """Get hexagonal neighbors (6-connected)."""
        ...

ContinuousSpace

Two-dimensional continuous space with real-valued coordinates.

from mesa.space import ContinuousSpace

class ContinuousSpace:
    """
    Two-dimensional continuous space with real-valued coordinates.
    
    Enables positioning agents at any (x, y) coordinate within defined bounds.
    """
    
    def __init__(self, x_max: float, y_max: float, torus: bool = False, 
                 x_min: float = 0, y_min: float = 0):
        """
        Initialize continuous space.
        
        Parameters:
            x_max: Maximum x coordinate
            y_max: Maximum y coordinate
            torus: Whether space wraps around at boundaries
            x_min: Minimum x coordinate
            y_min: Minimum y coordinate
        """
        ...
    
    def place_agent(self, agent, pos: FloatCoordinate):
        """
        Place an agent at continuous coordinates.
        
        Parameters:
            agent: Agent to place
            pos: (x, y) coordinate tuple with float values
        """
        ...
    
    def move_agent(self, agent, pos: FloatCoordinate):
        """Move an agent to new continuous coordinates."""
        ...
    
    def remove_agent(self, agent):
        """Remove an agent from the space."""
        ...
    
    def get_neighbors(self, pos: FloatCoordinate, radius: float, 
                     include_center: bool = False) -> List[Agent]:
        """
        Get agents within radius of position.
        
        Parameters:
            pos: Center position
            radius: Search radius
            include_center: Whether to include agent at exact center
        """
        ...
    
    def get_heading(self, pos_1: FloatCoordinate, pos_2: FloatCoordinate) -> float:
        """Get heading from pos_1 to pos_2 in radians."""
        ...
    
    def get_distance(self, pos_1: FloatCoordinate, pos_2: FloatCoordinate) -> float:
        """Get Euclidean distance between positions."""
        ...
    
    def move_by(self, agent, dx: float, dy: float):
        """Move agent by relative displacement."""
        ...
    
    def torus_adj(self, pos: FloatCoordinate) -> FloatCoordinate:
        """Adjust position for torus topology."""
        ...

NetworkGrid

Network-based space where agents are positioned on graph nodes.

from mesa.space import NetworkGrid
import networkx as nx

class NetworkGrid:
    """
    Network-based space where agents are positioned on nodes.
    
    Uses NetworkX graphs to define spatial structure and connectivity.
    """
    
    def __init__(self, G: nx.Graph):
        """
        Initialize network grid.
        
        Parameters:
            G: NetworkX graph defining the network structure
        """
        ...
    
    def place_agent(self, agent, node_id: NetworkCoordinate):
        """
        Place agent on a network node.
        
        Parameters:
            agent: Agent to place
            node_id: Network node identifier
        """
        ...
    
    def move_agent(self, agent, node_id: NetworkCoordinate):
        """Move agent to a different node."""
        ...
    
    def remove_agent(self, agent):
        """Remove agent from the network."""
        ...
    
    def get_neighbors(self, node_id: NetworkCoordinate) -> List[NetworkCoordinate]:
        """Get neighboring nodes in the network."""
        ...
    
    def get_all_cell_contents(self) -> List[Agent]:
        """Get all agents in the network."""
        ...
    
    def get_cell_list_contents(self, cell_list: List[NetworkCoordinate]) -> List[Agent]:
        """Get agents on specified nodes."""
        ...
    
    def iter_neighbors(self, node_id: NetworkCoordinate) -> Iterator[Agent]:
        """Iterate over agents on neighboring nodes."""
        ...

Modern Discrete Spatial System (mesa.discrete_space)

The modern discrete spatial system introduces a cell-centric approach with enhanced capabilities for property-rich spatial modeling. This system is under active development and represents the future of Mesa's spatial functionality.

Core Classes

Cell

Active positions that can have properties and contain agents.

from mesa.discrete_space import Cell

class Cell:
    """
    Active positions that can have properties and contain agents.
    
    Cells are first-class objects that can store properties, execute behaviors,
    and manage their agent occupants.
    """
    
    def __init__(self, coordinate: Coordinate, capacity: int | None = None):
        """
        Initialize a cell.
        
        Parameters:
            coordinate: The cell's position coordinate
            capacity: Maximum number of agents (None for unlimited)
        """
        ...
    
    def add_agent(self, agent):
        """Add an agent to this cell."""
        ...
    
    def remove_agent(self, agent):
        """Remove an agent from this cell."""
        ...
    
    @property
    def agents(self) -> List[Agent]:
        """Get all agents in this cell."""
        ...
    
    @property
    def coordinate(self) -> Coordinate:
        """Get the cell's coordinate."""
        ...
    
    @property
    def is_empty(self) -> bool:
        """Check if cell contains no agents."""
        ...
    
    @property
    def is_full(self) -> bool:
        """Check if cell is at capacity."""
        ...
    
    def get_neighborhood(self, radius: int = 1) -> 'CellCollection':
        """Get neighboring cells within radius."""
        ...

CellAgent

Base agent class that understands cell-based spatial interactions.

from mesa.discrete_space import CellAgent

class CellAgent(Agent):
    """
    Base agent class that understands cell-based spatial interactions.
    
    Extends the basic Agent class with cell-aware spatial behavior
    and movement capabilities.
    """
    
    def __init__(self, model, cell: Cell | None = None):
        """
        Initialize a CellAgent.
        
        Parameters:
            model: The model instance
            cell: Initial cell position (optional)
        """
        super().__init__(model)
        ...
    
    @property
    def cell(self) -> Cell | None:
        """Get the cell this agent occupies."""
        ...
    
    @property
    def coordinate(self) -> Coordinate | None:
        """Get the agent's coordinate position."""
        ...
    
    def move_to(self, cell: Cell):
        """
        Move this agent to a different cell.
        
        Parameters:
            cell: Target cell to move to
        """
        ...
    
    def get_neighbors(self, radius: int = 1, include_center: bool = False) -> List['CellAgent']:
        """
        Get neighboring agents within radius.
        
        Parameters:
            radius: Search radius in cells
            include_center: Whether to include agents in same cell
        """
        ...
    
    def get_neighborhood_cells(self, radius: int = 1) -> 'CellCollection':
        """Get neighboring cells within radius."""
        ...

FixedAgent

Specialized agent class for immobile entities permanently fixed to cells.

from mesa.discrete_space import FixedAgent

class FixedAgent(Agent):
    """
    Agent permanently fixed to a cell position.
    
    FixedAgent represents patches or immobile entities that are bound to
    specific cells and cannot move. Useful for terrain features, buildings,
    or other static environmental elements.
    """
    
    def remove(self):
        """Remove the agent from the model and cell."""
        ...

Grid2DMovingAgent

Specialized agent class with enhanced 2D grid movement capabilities.

from mesa.discrete_space import Grid2DMovingAgent

class Grid2DMovingAgent(CellAgent):
    """
    Mixin for agents with directional movement in 2D grids.
    
    Provides convenient movement methods using cardinal and ordinal directions,
    with support for string-based direction commands like 'north', 'southeast', etc.
    """
    
    DIRECTION_MAP = {
        "n": (-1, 0), "north": (-1, 0), "up": (-1, 0),
        "s": (1, 0), "south": (1, 0), "down": (1, 0),
        "e": (0, 1), "east": (0, 1), "right": (0, 1),
        "w": (0, -1), "west": (0, -1), "left": (0, -1),
        "ne": (-1, 1), "northeast": (-1, 1), "upright": (-1, 1),
        "nw": (-1, -1), "northwest": (-1, -1), "upleft": (-1, -1),
        "se": (1, 1), "southeast": (1, 1), "downright": (1, 1),
        "sw": (1, -1), "southwest": (1, -1), "downleft": (1, -1)
    }
    
    def move_by_direction(self, direction: str | tuple[int, int]):
        """
        Move agent by direction string or coordinate offset.
        
        Parameters:
            direction: Direction string (e.g., 'north') or coordinate tuple
        """
        ...

Grid Implementations

Grid

Base grid implementation for cell spaces.

from mesa.discrete_space import Grid

class Grid(DiscreteSpace):
    """
    Base grid implementation for cell spaces.
    
    Provides orthogonal grid structure with configurable neighborhood types
    and boundary conditions.
    """
    
    def __init__(self, width: int, height: int, torus: bool = False, 
                 capacity: int | None = None):
        """
        Initialize a grid.
        
        Parameters:
            width: Grid width in cells
            height: Grid height in cells
            torus: Whether grid wraps at boundaries
            capacity: Default cell capacity (None for unlimited)
        """
        ...
    
    def place_agent(self, agent: CellAgent, cell: Cell):
        """Place an agent in a specific cell."""
        ...
    
    def move_agent(self, agent: CellAgent, cell: Cell):
        """Move an agent to a different cell."""
        ...
    
    def remove_agent(self, agent: CellAgent):
        """Remove an agent from the grid."""
        ...
    
    def select_random_empty_cell(self) -> Cell:
        """Select a random empty cell."""
        ...
    
    def get_cell(self, coordinate: Coordinate) -> Cell:
        """Get cell at specific coordinate."""
        ...
    
    def get_cells(self) -> CellCollection:
        """Get all cells in the grid."""
        ...
    
    def get_empty_cells(self) -> CellCollection:
        """Get all empty cells."""
        ...
    
    @property
    def width(self) -> int:
        """Grid width."""
        ...
    
    @property  
    def height(self) -> int:
        """Grid height."""
        ...

OrthogonalMooreGrid

Grid with 8-neighbor (Moore) connectivity pattern.

from mesa.discrete_space import OrthogonalMooreGrid

class OrthogonalMooreGrid(Grid):
    """
    Grid with 8-neighbor (Moore) connectivity.
    
    Provides Moore neighborhood where each cell has up to 8 neighbors
    (including diagonal connections). In n-dimensional space, provides
    (3^n)-1 neighbors per cell.
    """
    
    def __init__(self, width: int, height: int, torus: bool = False, capacity: int | None = None):
        """
        Initialize Moore grid.
        
        Parameters:
            width: Grid width
            height: Grid height  
            torus: Whether grid wraps around edges
            capacity: Maximum agents per cell (None for unlimited)
        """
        ...

OrthogonalVonNeumannGrid

Grid with 4-neighbor (Von Neumann) connectivity pattern.

from mesa.discrete_space import OrthogonalVonNeumannGrid

class OrthogonalVonNeumannGrid(Grid):
    """
    Grid with 4-neighbor (Von Neumann) connectivity.
    
    Provides Von Neumann neighborhood where each cell has up to 4 neighbors
    (only orthogonal connections, no diagonals). In n-dimensional space,
    provides 2n neighbors per cell.
    """
    
    def __init__(self, width: int, height: int, torus: bool = False, capacity: int | None = None):
        """
        Initialize Von Neumann grid.
        
        Parameters:
            width: Grid width
            height: Grid height
            torus: Whether grid wraps around edges  
            capacity: Maximum agents per cell (None for unlimited)
        """
        ...

HexGrid

Hexagonal grid arrangement with 6-neighbor connectivity.

from mesa.discrete_space import HexGrid

class HexGrid(DiscreteSpace):
    """
    Hexagonal grid arrangement with 6-neighbor connectivity.
    
    Provides hexagonal tessellation for models requiring 6-neighbor
    spatial relationships.
    """
    
    def __init__(self, width: int, height: int, torus: bool = False):
        """
        Initialize hexagonal grid.
        
        Parameters:
            width: Grid width in hexagonal cells
            height: Grid height in hexagonal cells  
            torus: Whether grid wraps at boundaries
        """
        ...
    
    # Inherits base grid methods with hexagonal geometry

Network

Network-based cell arrangement using graph structures.

from mesa.discrete_space import Network
import networkx as nx

class Network(DiscreteSpace):
    """
    Network-based cell arrangement using graph structures.
    
    Enables spatial modeling on arbitrary network topologies
    using NetworkX graphs.
    """
    
    def __init__(self, graph: nx.Graph):
        """
        Initialize network space.
        
        Parameters:
            graph: NetworkX graph defining connectivity
        """
        ...
    
    def get_cell(self, node_id) -> Cell:
        """Get cell corresponding to network node."""
        ...
    
    def get_neighbors(self, cell: Cell) -> CellCollection:
        """Get neighboring cells in the network."""
        ...

Property Layers

Property layers provide efficient storage and manipulation of spatial properties across cells.

from mesa.discrete_space import PropertyLayer

class PropertyLayer:
    """
    Efficient property storage and manipulation for spatial models.
    
    Enables storing and updating scalar or array properties across
    spatial cells with optimized operations.
    """
    
    def __init__(self, name: str, width: int, height: int, 
                 default_value: Any = 0, dtype=None):
        """
        Initialize property layer.
        
        Parameters:
            name: Layer name identifier
            width: Layer width
            height: Layer height
            default_value: Default cell value
            dtype: NumPy data type
        """
        ...
    
    def set_cell(self, coordinate: Coordinate, value: Any):
        """Set value at specific coordinate."""
        ...
    
    def get_cell(self, coordinate: Coordinate) -> Any:
        """Get value at specific coordinate."""
        ...
    
    def set_cells(self, coordinates: List[Coordinate], values: Any):
        """Set values at multiple coordinates."""
        ...
    
    def get_cells(self, coordinates: List[Coordinate]) -> List[Any]:
        """Get values at multiple coordinates."""
        ...
    
    def modify_cells(self, coordinates: List[Coordinate], 
                    operation: Callable, *args, **kwargs):
        """Apply operation to modify cell values."""
        ...
    
    def apply_operation(self, operation: Callable, *args, **kwargs):
        """Apply operation to all cells."""
        ...
    
    @property
    def data(self) -> np.ndarray:
        """Access underlying NumPy array."""
        ...

Usage Examples

Traditional Grid Usage

from mesa import Agent, Model
from mesa.space import MultiGrid
from mesa.datacollection import DataCollector

class TraditionalAgent(Agent):
    def __init__(self, model, energy=100):
        super().__init__(model)
        self.energy = energy
    
    def step(self):
        # Move to random neighboring cell
        neighbors = self.model.grid.get_neighborhood(
            self.pos, moore=True, include_center=False
        )
        new_pos = self.random.choice(neighbors)
        self.model.grid.move_agent(self, new_pos)
        
        # Interact with agents in same cell
        cellmates = self.model.grid.get_cell_list_contents([self.pos])
        for other in cellmates:
            if other != self and isinstance(other, TraditionalAgent):
                # Simple energy transfer
                transfer = min(5, self.energy // 2)
                self.energy -= transfer
                other.energy += transfer

class TraditionalModel(Model):
    def __init__(self, n_agents=50, width=20, height=20):
        super().__init__()
        
        # Create traditional grid
        self.grid = MultiGrid(width, height, torus=True)
        
        # Create agents and place randomly
        for i in range(n_agents):
            agent = TraditionalAgent(self, energy=100)
            x = self.random.randrange(width)
            y = self.random.randrange(height)
            self.grid.place_agent(agent, (x, y))
        
        self.running = True
    
    def step(self):
        self.agents.shuffle_do("step")

# Usage
model = TraditionalModel(n_agents=30, width=15, height=15)
for i in range(50):
    model.step()

Modern Cell-Space Usage

from mesa import Model
from mesa.discrete_space import Grid, CellAgent, PropertyLayer

class ModernAgent(CellAgent):
    def __init__(self, model, cell=None, energy=100):
        super().__init__(model, cell)
        self.energy = energy
    
    def step(self):
        # Get neighboring cells
        neighbors = self.get_neighborhood_cells(radius=1)
        empty_neighbors = neighbors.select_cells(lambda c: c.is_empty)
        
        if empty_neighbors:
            # Move to random empty neighboring cell
            new_cell = self.random.choice(empty_neighbors)
            self.move_to(new_cell)
        
        # Interact with nearby agents
        nearby_agents = self.get_neighbors(radius=1, include_center=True)
        for other in nearby_agents:
            if other != self:
                # Energy sharing
                avg_energy = (self.energy + other.energy) / 2
                self.energy = avg_energy
                other.energy = avg_energy
        
        # Update cell property
        if hasattr(self.model, 'temperature_layer'):
            current_temp = self.model.temperature_layer.get_cell(self.coordinate)
            # Agents increase local temperature
            self.model.temperature_layer.set_cell(self.coordinate, current_temp + 0.1)

class ModernModel(Model):
    def __init__(self, n_agents=50, width=20, height=20):
        super().__init__()
        
        # Create modern grid
        self.space = Grid(width, height, torus=True)
        
        # Create property layer for temperature
        self.temperature_layer = PropertyLayer(
            "temperature", width, height, default_value=20.0
        )
        
        # Create agents and place randomly
        for i in range(n_agents):
            agent = ModernAgent(self, energy=100)
            empty_cell = self.space.select_random_empty_cell()
            self.space.place_agent(agent, empty_cell)
        
        self.running = True
    
    def step(self):
        # Execute agent behaviors
        self.agents.shuffle_do("step")
        
        # Update environment - cool down temperature
        self.temperature_layer.apply_operation(
            lambda temp: max(20.0, temp * 0.95)  # Cool towards base temperature
        )

# Usage
model = ModernModel(n_agents=30, width=15, height=15)
for i in range(50):
    model.step()

# Access spatial data
hot_cells = []
for cell in model.space.get_cells():
    temp = model.temperature_layer.get_cell(cell.coordinate)
    if temp > 25.0:
        hot_cells.append(cell)

print(f"Hot spots: {len(hot_cells)} cells above 25°C")

Continuous Space Usage

from mesa import Agent, Model
from mesa.space import ContinuousSpace
import math

class ContinuousAgent(Agent):
    def __init__(self, model, pos, speed=1.0):
        super().__init__(model)
        self.pos = pos
        self.speed = speed
        self.heading = self.random.uniform(0, 2 * math.pi)
    
    def step(self):
        # Move in current direction
        dx = math.cos(self.heading) * self.speed
        dy = math.sin(self.heading) * self.speed
        self.model.space.move_by(self, dx, dy)
        
        # Avoid crowding - turn away from nearby agents
        neighbors = self.model.space.get_neighbors(self.pos, radius=3.0)
        if len(neighbors) > 3:
            # Calculate average position of neighbors
            avg_x = sum(n.pos[0] for n in neighbors) / len(neighbors)
            avg_y = sum(n.pos[1] for n in neighbors) / len(neighbors)
            
            # Turn away from crowd
            away_heading = self.model.space.get_heading(
                (avg_x, avg_y), self.pos
            )
            self.heading = away_heading + self.random.uniform(-0.5, 0.5)
        
        # Random walk component
        self.heading += self.random.uniform(-0.1, 0.1)

class ContinuousModel(Model):
    def __init__(self, n_agents=100, width=50.0, height=50.0):
        super().__init__()
        
        # Create continuous space
        self.space = ContinuousSpace(width, height, torus=True)
        
        # Create agents at random positions
        for i in range(n_agents):
            x = self.random.uniform(0, width)
            y = self.random.uniform(0, height)
            agent = ContinuousAgent(self, (x, y), speed=self.random.uniform(0.5, 2.0))
            self.space.place_agent(agent, (x, y))
        
        self.running = True
    
    def step(self):
        self.agents.shuffle_do("step")

# Usage
model = ContinuousModel(n_agents=50, width=30.0, height=30.0)
for i in range(100):
    model.step()

Network Space Usage

from mesa import Agent, Model
from mesa.space import NetworkGrid
import networkx as nx

class NetworkAgent(Agent):
    def __init__(self, model, node_id):
        super().__init__(model)
        self.node_id = node_id
        self.infection_status = "susceptible"
    
    def step(self):
        if self.infection_status == "infected":
            # Spread infection to neighbors
            neighbors = self.model.grid.get_neighbors(self.pos)
            for neighbor_node in neighbors:
                neighbor_agents = self.model.grid.get_cell_list_contents([neighbor_node])
                for agent in neighbor_agents:
                    if (agent.infection_status == "susceptible" and 
                        self.random.random() < 0.1):  # 10% transmission rate
                        agent.infection_status = "infected"
        
        elif self.infection_status == "susceptible":
            # Random movement
            neighbors = self.model.grid.get_neighbors(self.pos)
            if neighbors:
                new_node = self.random.choice(neighbors)
                self.model.grid.move_agent(self, new_node)

class NetworkModel(Model):
    def __init__(self, network_type="small_world", n_nodes=100):
        super().__init__()
        
        # Create network
        if network_type == "small_world":
            G = nx.watts_strogatz_graph(n_nodes, 6, 0.3)
        elif network_type == "scale_free":
            G = nx.barabasi_albert_graph(n_nodes, 3)
        else:
            G = nx.erdos_renyi_graph(n_nodes, 0.1)
        
        self.grid = NetworkGrid(G)
        
        # Create agents on random nodes
        nodes = list(G.nodes())
        for i, node in enumerate(nodes):
            agent = NetworkAgent(self, node)
            self.grid.place_agent(agent, node)
        
        # Patient zero
        if self.agents:
            patient_zero = self.random.choice(self.agents)
            patient_zero.infection_status = "infected"
        
        self.running = True
    
    def step(self):
        self.agents.shuffle_do("step")
        
        # Check if infection has spread to everyone or died out
        infected = len([a for a in self.agents if a.infection_status == "infected"])
        if infected == 0 or infected == len(self.agents):
            self.running = False

# Usage
model = NetworkModel("small_world", n_nodes=50)
for i in range(100):
    model.step()
    if not model.running:
        break

infected_count = len([a for a in model.agents if a.infection_status == "infected"])
print(f"Final infected count: {infected_count}/{len(model.agents)}")

Choosing Between Spatial Systems

Use Traditional mesa.space When:

  • Working with existing Mesa models that use the traditional system
  • Need well-tested, stable spatial functionality
  • Building simple grid-based models without complex spatial properties
  • Prioritize compatibility with Mesa 2.x models

Use Modern mesa.discrete_space When:

  • Building new models from scratch
  • Need property-rich spatial environments
  • Want cell-centric spatial modeling
  • Require advanced spatial operations and queries
  • Planning to use experimental Mesa features

Migration Considerations

# Traditional approach
from mesa.space import MultiGrid

class OldModel(Model):
    def __init__(self):
        self.grid = MultiGrid(10, 10, True)
        # Traditional grid operations...

# Modern approach - similar functionality with enhanced capabilities
from mesa.discrete_space import Grid

class NewModel(Model):  
    def __init__(self):
        self.space = Grid(10, 10, torus=True)
        # Modern grid operations with cells and property layers...

docs

batch-running.md

core.md

data-collection.md

experimental.md

index.md

spatial.md

tile.json