Skip to content

1503 add python bindings for ABM#1515

Open
charlie0614 wants to merge 11 commits intomainfrom
1503-add-python-bindings-for-abm
Open

1503 add python bindings for ABM#1515
charlie0614 wants to merge 11 commits intomainfrom
1503-add-python-bindings-for-abm

Conversation

@charlie0614
Copy link
Copy Markdown
Member

@charlie0614 charlie0614 commented Mar 24, 2026

Changes and Information

Please briefly list the changes (main added features, changed items, or corrected bugs) made:

  • Add python bindings for minimal ABM example

Merge Request - Guideline Checklist

Please check our git workflow. Use the draft feature if the Pull Request is not yet ready to review.

Checks by code author

  • Every addressed issue is linked (use the "Closes #ISSUE" keyword below).
  • New code adheres to coding guidelines.
  • No large data files have been added (files should in sum not exceed 100 KB, avoid PDFs, Word docs, etc.).
  • Tests are added for new functionality and a local test run was successful (with and without OpenMP).
  • Appropriate documentation within the code (Doxygen) for new functionality has been added in the code.
  • Appropriate external documentation (ReadTheDocs) for new functionality has been added to the online documentation and checked in the preview.
  • Proper attention to licenses, especially no new third-party software with conflicting license has been added.
  • (For ABM development) Checked benchmark results and ran and posted a local test above from before and after development to ensure performance is monitored.

Checks by code reviewer(s)

  • Corresponding issue(s) is/are linked and addressed.
  • Code is clean of development artifacts (no deactivated or commented code lines, no debugging printouts, etc.).
  • Appropriate unit tests have been added, CI passes, code coverage and performance is acceptable (did not decrease).
  • No large data files added in the whole history of commits(files should in sum not exceed 100 KB, avoid PDFs, Word docs, etc.).
  • On merge, add 2-5 lines with the changes (main added features, changed items, or corrected bugs) to the merge-commit-message. This can be taken from the briefly-list-the-changes above (best case) or the separate commit messages (worst case).

Closes #1503

@charlie0614 charlie0614 linked an issue Mar 24, 2026 that may be closed by this pull request
2 tasks
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.38%. Comparing base (8f90ce7) to head (43cb996).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1515   +/-   ##
=======================================
  Coverage   97.38%   97.38%           
=======================================
  Files         188      188           
  Lines       16621    16621           
=======================================
  Hits        16186    16186           
  Misses        435      435           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Member

@DavidKerkmann DavidKerkmann left a comment

Choose a reason for hiding this comment

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

There are a couple of generalized questions that we need to tackle now that we are bringing python bindings to the simulation level.

template <class T>
concept HasSampleFunction = requires(T t) {
{ t.get_sample(std::declval<RandomNumberGenerator&>()) } -> std::convertible_to<ScalarType>;
{ t.get_sample(std::declval<abm::PersonalRandomNumberGenerator&>()) } -> std::convertible_to<ScalarType>;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The abstract parameter disctribution is in utils/ and should remain model-independent. An abm::PersonalRandomNumberGenerator is only known when there is knowledge about the ABM..
Is this required at this point? Requiring an abm::PRNG makes this unusable for other models.

Comment on lines +38 to +39
model.parameters.AgeGroupGotoSchool[AgeGroup(age_group)] = False
model.parameters.AgeGroupGotoWork[AgeGroup(age_group)] = False
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As the default is false, these line could be removed, unless you have an intention to explicitly write them down.

Comment on lines +45 to +52
for age in range(num_age_groups):
model.parameters.InfectionProtectionFactor[abm.ProtectionType.GenericVaccine, AgeGroup(
age), abm.VirusVariant.Wildtype] = mio.TimeSeriesFunctor(
[[0, 0.0], [14, 0.67], [180, 0.4]])

model.parameters.SeverityProtectionFactor[abm.ProtectionType.GenericVaccine, AgeGroup(
age), abm.VirusVariant.Wildtype] = mio.TimeSeriesFunctor(
[[0, 0.0], [14, 0.85], [180, 0.7]])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This part is not in the .cpp file. We should probably stay as close as possible to the .cpp example. If we want to add this, then we should also add it in the .cpp example.

# Seed infections

infection_distribution = [0.5, 0.3, 0.05, 0.05, 0.05, 0.05, 0.0, 0.0]
rng = np.random.default_rng()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

With the availability of the MEmilio RNG / Personal RNG we should use that one here instead of the numpy rng. The discrete distribution would be suitable.

.def_property_readonly("is_in_quarantine", &mio::abm::Person::is_in_quarantine);
.def_property_readonly("is_in_quarantine", &mio::abm::Person::is_in_quarantine)
.def_property_readonly("id", &mio::abm::Person::get_id)
.def("add_new_infection",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see that this looked different at some point. Normally, as far as I can tell, we always bind the functions 1:1, meaning that we use the same arguments as in the cpp code. Here, the model is passed instead of the rng, and then the function itself creates the PRNG. However, then we could go a step further and also remove the age for example, as it could also be inferred directly from the person.

In general, we should decide how we want to go about these things. In a way, we lose flexibility if the user intends to use a different rng for some reason here. However, I think it also simplifies the use and perhaps we could bind functions for easier use in general.

Comment on lines +272 to +284
.def(
"advance",
[](mio::abm::Simulation<>& sim, mio::abm::TimePoint tmax) {
sim.advance(tmax);
},
py::arg("tmax"))
.def(
"advance",
[](mio::abm::Simulation<>& sim, mio::abm::TimePoint tmax,
mio::History<mio::abm::TimeSeriesWriter, mio::abm::LogInfectionState>& history) {
sim.advance(tmax, history);
},
py::arg("tmax"), py::arg("history"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This only allows for two specific advance calls. A general functionality with any history object would be preferred (in conjuction with the binding of the History).

{
bind_class<mio::AbstractParameterDistribution, EnablePickling::Never>(m, name.c_str())
.def(py::init<>())
.def(py::init<mio::ParameterDistributionLogNormal>(), py::arg("dist"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be generic for any distribution (see templated definition).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add python bindings for ABM

2 participants