Skip to content

Fix non-deterministic meta-agent membership assignment (#3184)#3433

Merged
tpike3 merged 6 commits intomesa:mainfrom
codebyNJ:fix/meta-agents-membership-3184
Mar 25, 2026
Merged

Fix non-deterministic meta-agent membership assignment (#3184)#3433
tpike3 merged 6 commits intomesa:mainfrom
codebyNJ:fix/meta-agents-membership-3184

Conversation

@codebyNJ
Copy link
Copy Markdown
Contributor

@codebyNJ codebyNJ commented Mar 4, 2026

Pre-PR Checklist

  • This PR is a bug fix, not a new feature or enhancement.

Summary

Fixes #3184agent.meta_agent was set non-deterministically when an agent belongs to multiple meta-agents.

Bug / Issue

Three locations in meta_agent.py blindly set agent.meta_agent = self without checking existing memberships:

  • MetaAgent.__init__ (line 315) — overwrites any existing assignment
  • add_constituting_agents (line 391) — same issue
  • create_meta_agent path 1 (line 246) — iterates over a.meta_agents (set()) which has non-deterministic order

Different runs produce different agent.meta_agent pointers for the same model, breaking reproducibility.

Implementation

All three locations now pick the meta-agent with the lowest unique_id:

agent.meta_agent = sorted(
    agent.meta_agents, key=lambda x: x.unique_id or 0
)[0]

Consistent with the existing pattern in remove_constituting_agents (lines 404-409).

Testing

All 20 meta-agent tests pass. No new tests needed — fix makes existing behavior deterministic without changing semantics.

Additional Notes

None.


GSoC contributor checklist

Context & motivation

I found this bug while reading through #3184 and tracing how overlapping membership works in meta-agents. agent.meta_agent was just being set to self everywhere without checking if the agent already belonged to another meta-agent. The pointer ends up depending on creation order, which is not predictable. Reproducibility matters for any simulation framework — same inputs should give same outputs.

What I learned

The interesting part was that remove_constituting_agents already had the correct deterministic pattern (sorting by unique_id) but __init__ and add_constituting_agents didn't follow it. I also learned that iterating over a Python set() is non-deterministic across runs, so even the create_meta_agent path needed sorting. The fix was about consistency — applying the same pattern that already existed in one place to the others that were missing it.

Learning repo

My learning repo: https://github.com/codebyNJ/GSoC-learning-space

Readiness checks

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 4, 2026

Performance benchmarks:

Model Size Init time [95% CI] Run time [95% CI]
BoltzmannWealth small 🔵 -0.3% [-0.8%, +0.0%] 🔵 -0.4% [-0.6%, -0.3%]
BoltzmannWealth large 🔵 -1.1% [-1.6%, -0.6%] 🔵 -2.3% [-3.5%, -1.2%]
Schelling small 🔵 -0.6% [-0.9%, -0.3%] 🔵 -0.5% [-0.6%, -0.4%]
Schelling large 🔵 -1.2% [-1.7%, -0.6%] 🔵 -2.9% [-3.7%, -2.2%]
WolfSheep small 🔵 -2.3% [-2.7%, -1.9%] 🔵 -1.4% [-1.6%, -1.2%]
WolfSheep large 🔵 +0.5% [-0.6%, +1.5%] 🔵 -0.5% [-2.3%, +1.1%]
SugarscapeG1mt small 🔵 +0.0% [-0.4%, +0.5%] 🔵 -1.0% [-1.2%, -0.8%]
SugarscapeG1mt large 🔵 -3.0% [-4.5%, -1.2%] 🔵 -2.0% [-2.2%, -1.8%]
BoidFlockers small 🔵 -0.5% [-1.0%, -0.0%] 🔵 -2.1% [-2.2%, -1.8%]
BoidFlockers large 🔵 +0.2% [-0.1%, +0.6%] 🔵 -0.8% [-1.0%, -0.5%]

@tpike3 tpike3 self-assigned this Mar 8, 2026
@tpike3
Copy link
Copy Markdown
Member

tpike3 commented Mar 16, 2026

@codebyNJ apologies for the delay, I was unable to do reviews dealing with non-Mesa issues, but I am am back now.

Could you please update this following --- #3536

Please let me know if you have any questions as we refine this process.

@codebyNJ
Copy link
Copy Markdown
Contributor Author

@tpike3, no worries at all! I have updated this PR with the GSoC checklist from #3536. I'll also update my other open meta-agent PRs (#3506, #3538) with the same format. Thanks for reviewing!

Copy link
Copy Markdown
Member

@tpike3 tpike3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @codebyNJ, typically I would not want to do an implicit policy for the user. However with the refactor coming up, and this being dealing with a legacy set up. I think this is allowable in this instance.

@tpike3 tpike3 merged commit c8b833e into mesa:main Mar 25, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

additional bugs in meta_agents

3 participants