mesa / mesa/mesa-examples

VirusAntibodyModel breaks the examples CI job on every mesa PR (create_agents dna broadcast bug)

Open
#488 0 comments 0 reactions 0 assignees View on GitHub
bug docs
Dominant language
Python
Stars
252
Forks
279
Avg merge
8d 9h
Merged PRs (30d)
2

Description

mesa/mesa-examples (the bug lives in the example; it just surfaces via mesa/mesa's CI, which checks out mesa-examples fresh on every PR)

## Summary

The `examples` job in mesa/mesa's CI (checks out `mesa-examples` and runs `test_examples.py` against the current build) fails consistently on `test_model_steps[VirusAntibodyModel]` — on every PR, regardless of what the PR actually changes. It's not flaky and it's not caused by any particular PR's diff.

## Error

```
ValueError: sequence of length 3 does not match the number of agents (20)
```

Raised from `mesa/agent.py`, inside `Agent.create_agents()` → `_resolve_per_agent_values()`. Seen across independent runs with only the random values changing:

```
value = [0, 7, 5], n = 20, strict = True
value = [9, 0, 9], n = 20, strict = True
value = [6, 8, 4], n = 20, strict = True
```

## Root cause

`create_agents(model, n, *args, **kwargs)` treats any `list` / `tuple` / `ndarray` / `pandas.Series` argument as "one value per agent" and requires it to have length `n`, raising `ValueError` otherwise. This is documented, intentional mesa-core behavior (see the Warning in `Agent.create_agents`'s docstring) — it is not a mesa-core bug.

In `examples/virus_antibody/agents.py`, `VirusAgent.generate_dna()` returns a fixed 3-element list:

```python
def generate_dna(self, dna=None):
if dna is None:
return [self.random.randint(0, 9) for _ in range(3)]
...
```

This is the model's "founder" virus DNA (later mutated per-lineage via `duplicate()`). When the model bulk-creates the initial virus population with something like `VirusAgent.create_agents(self, num_viruses, ..., dna=)`, `_resolve_per_agent_values` sees a length-3 list against `n = num_viruses` (20 in the test harness) and raises. Since the initial virus count is essentially never 3, this fails deterministically on every run.

> Note: I confirmed `generate_dna()`'s shape directly in `agents.py`, but couldn't pull the current `model.py` source to see the exact `create_agents(...)` call (GitHub's diff view for that file didn't come through in my fetch). The call site above is inferred with high confidence from the matching value shapes in the CI logs — worth a quick confirm against the actual line.

## Suggested fix

If all initial viruses are meant to share one founder strain, broadcast it explicitly so its length matches `n`:

```python
initial_dna = [self.random.randint(0, 9) for _ in range(3)]
...
VirusAgent.create_agents(
self,
num_viruses,
self.space,
mutation_rate,
duplication_rate,
position=virus_positions,
dna=[initial_dna] * num_viruses, # broadcast, not per-agent
)
```

If each initial virus should instead start with its own random DNA, generate one sub-list per agent so the outer list's length already equals `n`:

```python
dna=[[self.random.randint(0, 9) for _ in range(3)] for _ in range(num_viruses)]
```

Contributor guide

Open the contributing guide

Research direction

Start with examples/virus_antibody/agents.py to confirm generate_dna() and inspect the corresponding create_agents call in the model file. Run test_examples.py, especially test_model_steps[VirusAntibodyModel], then determine whether initial viruses should share one DNA value or receive independent DNA values. Done means the VirusAntibodyModel example passes consistently in the examples CI job.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.