Skip to content

virus antibody model #253

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

colinfrisch
Copy link
Collaborator

Virus-Antibody Model

This model is a simulation of immune reaction declined as a confrontation between antibody agents and virus agents. The global idea is to model how the imune system can struggle against new virus but is able to adapt over time and beat a same virus if it comes back. The results are quite interesting as the simulation can go both ways (virus win or antibodies win) with a little tweak in the base parameters (check the readme for some examples).

What it showcases

  • Usage of memory in agents : divided into a short term memory using a deque to easily add and remove memories in case of a new virus encounter, and a long term memory (here a simple list)
  • Agent knowledge sharing : the antibodies are able to share short term memory)
  • Usage of weak referencing to avoid coding errors (antibodies can store viruses in a self.target attribute)
  • Emergence of completely different outcomes with only small changes in parameters

What it adds to mesa-examples

  • Will be the first continuous‑space user example
  • Weak‑referencing and dual memory systems and share knowledge (cf. what it showcases)
  • Theme is original and quite different from what already exists in examples : shows the diversity of fields in which mesa can be useful

How It Works

  1. Initialization: The model initializes a population of viruses and antibodies in a continuous 2D space.
  2. Agent Behavior:
    • Antibodies move randomly until they detect a virus within their sight range (becomes purple), than pursue the virus.
    • Antibodies pass on all the virus DNA in their short term memory to the nearest antibodies (cf. example)
    • Viruses move randomly and can duplicate or mutate.
  3. Engagement (antibody vs virus): When an antibody encounters a virus:
    • If the antibody has the virus's DNA in its memory, it destroys the virus.
    • Otherwise, the virus may defeat the antibody, causing it to lose health or become inactive temporarily.
  4. Duplication: Antibodies and viruses can duplicate according to their duplication rate.
pattern

Copy link

coderabbitai bot commented Apr 18, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request introduces a simulation that models the interaction of viruses and antibodies in continuous space using the Mesa framework. The PR implements the core model logic, defines agent behaviors with dual memory systems and weak referencing, and sets up visualization components with an accompanying README for usage instructions.

  • Implements the core Virus/Antibody simulation with model parameters and agent scheduling.
  • Adds visualization components and parameter interfaces in the application module.
  • Documents the model details, simulation outcomes, and usage instructions in the README.

Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 4 comments.

File Description
examples/virus_antibody/model.py Implements the primary model setup and simulation step behavior.
examples/virus_antibody/app.py Provides the visualization interface and model parameter configurations.
examples/virus_antibody/agents.py Defines antibody and virus agent behaviors with memory, duplication, and engagement logic.
examples/virus_antibody/README.md Provides documentation covering model overview, usage, and simulation examples.
Files not reviewed (1)
  • examples/virus_antibody/requirements.txt: Language not supported

)

# Create and place the Antibody agents
antibodies_positions = self.rng.random(
Copy link
Preview

Copilot AI Apr 19, 2025

Choose a reason for hiding this comment

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

Inconsistent use of random number generators (self.rng vs self.random) may lead to unpredictable behavior; consider unifying these to a single random instance.

Copilot uses AI. Check for mistakes.

colinfrisch and others added 2 commits April 19, 2025 12:32
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

# Movement & state
self.position = initial_position
self.speed = 1.5
Copy link
Member

Choose a reason for hiding this comment

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

Would it be possible to make speed and health kwargs on the init? In my view it is good practice to make all attributes explicitly controllable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I made the choice of limiting the parameter to these ones because otherwise it's a lot for the user in my opinion. If I add all of them, it would mean more than 10 parameters to be decided by the user. Do you think I should still add all of the other parameters ? Or are there one or two more that would be good to add and still leave the others hidden (like ko_timeout, sight_range, and a few non-crucial parameters) ?

Copy link
Member

Choose a reason for hiding this comment

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

Fair enough. One option is to turn the constants that are the same for all agents of a given class into class level attributes. This still makes it easy to change them without having to add them all to the signature of the __init__.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good idea ! It does allow to delete quite a few lines of code in model.py also.


# Chase a valid virus target
else:
if getattr(target, "space", None) is not None:
Copy link
Member

Choose a reason for hiding this comment

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

again, this should not be needed if everything else is implemented correctly.

Copy link
Member

@quaquel quaquel left a comment

Choose a reason for hiding this comment

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

I have made a first pass. I like the idea of the model, but there is ample room for improvements. If you have questions, don't hesitate to ask.

self.lt_memory.append(dna)
self.ko_steps_left = self.ko_timeout
# mark KO state by weak-ref back to self
self.target = weakref.ref(self)
Copy link
Member

Choose a reason for hiding this comment

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

I dont understand what is going on here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

When an antibody looses a confrontation with a virus (because the virus DNA is not in it's memory yet), the antibody is ko for a few steps. It can't move during this time and I symbolise this by setting the agent's target to itself.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, clear.

This might be implemented using event scheduling, which would result in a modest speedup of runtime.

@colinfrisch
Copy link
Collaborator Author

Thanks a lot @quaquel for this first review ! I'm going to see what I can change asap

@quaquel
Copy link
Member

quaquel commented Apr 19, 2025

Thanks a lot @quaquel for this first review ! I'm going to see what I can change asap

I would start with the two sets in the the init of your model. Next, I would remove the if checks you have to see if an agent is still active in the model one at a time (or do one first to confirm the behavior is still correct). Again, don't hesitate to ask if you run into any issues.

@colinfrisch
Copy link
Collaborator Author

colinfrisch commented Apr 20, 2025

I would start with the two sets in the the init of your model. Next, I would remove the if checks you have to see if an agent is still active in the model one at a time (or do one first to confirm the behavior is still correct). Again, don't hesitate to ask if you run into any issues.

@quaquel I removed the checks and did the other fixes that you suggested. I still have one error that I don't understand, and it seems to be still linked to referencing. For certain configurations of parameters, the model runs for a while (even hundreds of steps) before making the error error in step: 'NoneType' object has no attribute 'agent_positions'. Even after debugging, I can't find the origin of it... would you have any idea to why it's happening ?

You can reproduce this error by keeping the base parameters and setting duplication rate to max in the sliders.

Screenshot 2025-04-20 at 18 27 20

Full traceback :

  File "/Users/colinfrisch/Desktop/mesa/mesa/visualization/solara_viz.py", line 275, in step
    do_step()
    ~~~~~~~^^
  File "/Users/colinfrisch/Desktop/mesa/mesa/mesa_logging.py", line 132, in wrapper
    res = func(*args, **kwargs)
  File "/Users/colinfrisch/Desktop/mesa/mesa/visualization/solara_viz.py", line 309, in do_step
    model.value.step()
    ~~~~~~~~~~~~~~~~^^
  File "/Users/colinfrisch/Desktop/mesa/mesa/model.py", line 122, in _wrapped_step
    self._user_step(*args, **kwargs)
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/Users/colinfrisch/Desktop/mesa-examples/examples/virus_antibody/model.py", line 131, in step
    self.agents.shuffle_do("step")
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^
  File "/Users/colinfrisch/Desktop/mesa/mesa/agent.py", line 345, in shuffle_do
    getattr(agent, method)(*args, **kwargs)
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/Users/colinfrisch/Desktop/mesa-examples/examples/virus_antibody/agents.py", line 185, in step
    self.move()
    ~~~~~~~~~^^
  File "/Users/colinfrisch/Desktop/mesa-examples/examples/virus_antibody/agents.py", line 221, in move
    self.position += self.direction * self.speed
    ^^^^^^^^^^^^^
  File "/Users/colinfrisch/Desktop/mesa/mesa/experimental/continuous_space/continuous_space_agents.py", line 34, in position
    return self.space.agent_positions[self.space._agent_to_index[self]]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'agent_positions'

@quaquel
Copy link
Member

quaquel commented Apr 20, 2025

I'll try to take a closer look asap. It indeed seems that step is called on an agent that has already been removed.

@quaquel quaquel closed this Apr 20, 2025
@quaquel quaquel reopened this Apr 20, 2025
return dna

def move(self):
# Random walk
Copy link
Member

Choose a reason for hiding this comment

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

Both agents have a random walk component. Might it be possible to implement this the same way for both and move it to a new super agent class from which both current agents derive?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It could be a good idea ! At first I thought it could also be used for the duplicate() method. However, there are a lot of parameters to take into account and the code is very short inside, so I don't think that it would really help to make it derive from a parent class.

So I the end, there is just a few lines for the random movement. Isn't a whole parent class a bit overkill ?

Copy link
Member

Choose a reason for hiding this comment

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

If the choice is between repeated code or a parent class, I prefer the parent class. Of course, in python you could also move the relevant code into a helper function (not really appropriate for random walks).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Alright, will do, thank you for the advice !
On another note, did you have time to check out why step was being called on a removed agent ?

Copy link
Member

Choose a reason for hiding this comment

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

Monday was a banking holiday so I had family obligations. I'll try to get to it today, but no promises unfortunately.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Of course, nothing urgent ! Only if you have time :)

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants