Skip to content

tpike3/mesa-frames

 
 

Repository files navigation

Mesa logo

mesa-frames

CI/CD CI Checks codecov
Package PyPI - Version PyPI - Downloads PyPI - Python Version
Meta linting - Ruff formatter - Ruff Hatch project Managed with uv
Chat chat

Scale Mesa beyond its limits

Classic Mesa stores each agent as a Python object, which quickly becomes a bottleneck at scale. mesa-frames reimagines agent storage using Polars DataFrames, so agents live in a columnar store rather than the Python heap.

You keep the Mesa-style Model / AgentSet structure, but updates are vectorized and memory-efficient.

Why it matters

  • 10× faster bulk updates on 10k+ agents (see Benchmarks)
  • 📊 Columnar execution via Polars: SIMD ops, multi-core support
  • 🔄 Declarative logic: agent rules as transformations, not Python loops
  • 🚀 Roadmap: Lazy queries and GPU support for even faster models

Who is it for?

  • Researchers needing to scale to tens or hundreds of thousands of agents
  • Users whose agent logic can be written as vectorized, set-based operations

Not a good fit if: your model depends on strict per-agent sequencing, complex non-vectorizable methods, or fine-grained identity tracking.


Why DataFrames?

DataFrames enable SIMD and columnar operations that are far more efficient than Python loops. mesa-frames currently uses Polars as its backend.

Feature mesa (classic) mesa-frames
Storage Python objects Polars DataFrame
Updates Loops Vectorized ops
Memory overhead High Low
Max agents (practical) ~10^3 ~10^6+

Benchmarks

Reproduce Benchmarks

mesa-frames consistently outperforms classic Mesa across both toy and canonical ABMs.

In the Boltzmann model, it maintains near-constant runtimes even as agent count rises, achieving up to 10× faster execution at scale.

In the more computation-intensive Sugarscape model, mesa-frames roughly halves total runtime.

We still have room to optimize performance further (see Roadmap).

Benchmark: Boltzmann Wealth

Benchmark: Sugarscape IG


Quick Start

Explore the Tutorials

  1. Install
   pip install mesa-frames

Or for development:

git clone https://github.com/mesa/mesa-frames.git
cd mesa-frames
uv sync --all-extras
  1. Create a model

    from mesa_frames import AgentSet, Model
    import polars as pl
    
    class MoneyAgents(AgentSet):
        def __init__(self, n: int, model: Model):
            super().__init__(model)
            self += pl.DataFrame({"wealth": pl.ones(n, eager=True)})
    
        def give_money(self):
            self.select(self.wealth > 0)
            other_agents = self.df.sample(n=len(self.active_agents), with_replacement=True)
            self["active", "wealth"] -= 1
            new_wealth = other_agents.group_by("unique_id").len()
            self[new_wealth, "wealth"] += new_wealth["len"]
    
        def step(self):
            self.do("give_money")
    
    class MoneyModelDF(Model):
        def __init__(self, N: int):
            super().__init__()
            self.sets += MoneyAgents(N, self)
    
        def step(self):
            self.sets.do("step")

Roadmap

Community contributions welcome — see the full roadmap

  • Transition to LazyFrames for optimization and GPU support
  • Auto-vectorize existing Mesa models via decorator
  • Increase possible Spaces (Network, Continuous...)
  • Refine the API to align to Mesa

License

Copyright © 2025 Adam Amer, Mesa team and contributors

Licensed under the Apache License, Version 2.0.

About

Extension of mesa for performance and scalability

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Python 100.0%