Implement unified time and scheduling API#2928
Closed
Conversation
|
Performance benchmarks:
|
This commit introduces a unified time and event scheduling API directly into the Model class, eliminating the need for separate Simulator objects. The core insight is that users shouldn't need to manage two objects (Model and Simulator) to run a simulation. By integrating scheduling into Model, we get a cleaner API: model.run(until=100) instead of creating a simulator, calling setup(), then run_until(). Implementation uses composition: a new Scheduler class handles all event scheduling and execution logic, while Model provides thin delegation methods. This keeps Model focused on agents and state while Scheduler handles time. Key changes: - Add Scheduler class in mesa/experimental/devs/scheduler.py - Add Model.schedule() for event scheduling (at= or after= syntax) - Add Model.run() with multiple termination options - Add Model.cancel() for canceling scheduled events - Deprecate ABMSimulator/DEVSimulator (still functional with warnings) Part of the unified time/event scheduling proposal (mesa#2921).
Introduce `@scheduled` decorator to explicitly mark methods for recurring execution during model runs. This replaces the implicit auto-scheduling of `step()` methods. Key changes: - Add `@scheduled(interval=1.0)` decorator in `scheduler.py` - Model scans for decorated methods after `__init__` completes via `__new__` wrapper - Undecorated `step()` methods still work but emit `FutureWarning` - Deprecate `run_model()` in favor of `model.run(condition=...)` - Deprecate `model.steps` counter (use `model.time` instead) - Remove `_step_duration` attribute (unused, never released)
43d0c8c to
7ed695c
Compare
Member
Author
|
A strategy might be moving the dependence to |
Member
Author
|
Cleaner attempt at implementing Explicitly kept two code paths: One for where Still not perfect, but I think more in the right direction. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a pathfinding PR for #2921, under active development. The goal is to explore the structure, design and API, and gather feedback before finalizing. Breaking changes may occur as we iterate.
Summary
This PR introduces a unified API for time advancement and event scheduling, integrating these capabilities directly into the Model class. It represents the first implementation step toward the design outlined in #2921.
Motive
Currently, Mesa's experimental discrete event simulation requires users to manage two separate objects:
This raises unnecessary questions: Why do I need a simulator? What's the difference between ABMSimulator and DEVSimulator? What does setup() do? For most users building standard ABMs, these questions shouldn't exist.
The deeper motivation is enabling a smooth progression from simple step-based models to full discrete-event simulation without rewriting code. A user should be able to:
step()andrun(steps=100)model.schedule(drought, at=50))self.model.schedule(self.release, after=sentence))All using the same unified API, without switching between different simulator classes or paradigms.
Implementation
The implementation uses composition to keep concerns separated:
Scheduler(new class inscheduler.py): Owns the EventList and implements all scheduling/execution logicModel: Adds thin delegation methods (schedule(),run(),cancel()) that forward to the internal SchedulerSimulatorclasses: Deprecated but still functional, now delegate to Model's APIThis design keeps Model focused (~50 new lines) while the Scheduler contains the complexity (~150 lines). The Scheduler can be tested independently and potentially subclassed for custom behavior.
Usage Examples
API is non-final, we're currently exploring both keyword argument and separate method APIs. This implemenation uses keyword arguments.
Simple step-based model (unchanged):
Adding scheduled events:
Migration from old API:
Additional Notes
What this PR does NOT include (yet):
recurringparameter for automatic method scheduling (needs more design discussion)@scheduled)Open questions for reviewers:
_schedulerbe public (scheduler) for advanced users?Related:
mesa/experimental/devs/