{"id":32612836,"url":"https://github.com/uofuepibio/epiworld","last_synced_at":"2026-04-24T07:05:21.342Z","repository":{"id":39674568,"uuid":"435257025","full_name":"UofUEpiBio/epiworld","owner":"UofUEpiBio","description":"A general framework for quick epidemiological ABM models","archived":false,"fork":false,"pushed_at":"2026-01-28T23:42:57.000Z","size":26155,"stargazers_count":7,"open_issues_count":29,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-29T14:14:24.524Z","etag":null,"topics":["abm","agent-based-modeling","contagion","simulation"],"latest_commit_sha":null,"homepage":"https://uofuepibio.github.io/epiworld/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UofUEpiBio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-12-05T19:18:08.000Z","updated_at":"2026-01-26T21:22:26.000Z","dependencies_parsed_at":"2024-02-03T17:24:40.943Z","dependency_job_id":"658a711a-c332-4d08-8c9a-2378ff5b1cf2","html_url":"https://github.com/UofUEpiBio/epiworld","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/UofUEpiBio/epiworld","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UofUEpiBio%2Fepiworld","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UofUEpiBio%2Fepiworld/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UofUEpiBio%2Fepiworld/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UofUEpiBio%2Fepiworld/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UofUEpiBio","download_url":"https://codeload.github.com/UofUEpiBio/epiworld/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UofUEpiBio%2Fepiworld/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29054073,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T15:43:47.601Z","status":"ssl_error","status_checked_at":"2026-02-03T15:43:46.709Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["abm","agent-based-modeling","contagion","simulation"],"created_at":"2025-10-30T14:57:24.913Z","updated_at":"2026-04-24T07:05:21.334Z","avatar_url":"https://github.com/UofUEpiBio.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Tests and coverage](https://github.com/UofUEpi/epiworld/actions/workflows/test.yml/badge.svg)](https://github.com/UofUEpi/epiworld/actions/workflows/test.yml)\n[![C++ Documentation](https://img.shields.io/badge/Docs-Doxygen-brightgreen)](https://UofUEpi.github.io/epiworld)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/UofUEpiBio/epiworld)\n![GitHub Release](https://img.shields.io/github/v/release/UofUEpiBio/epiworld)\n[![codecov](https://codecov.io/gh/UofUEpiBio/epiworld/graph/badge.svg?token=CPDYG4HA0B)](https://codecov.io/gh/UofUEpiBio/epiworld)\n[![ForeSITE Group](https://github.com/EpiForeSITE/software/raw/e82ed88f75e0fe5c0a1a3b38c2b94509f122019c/docs/assets/foresite-software-badge.svg)](https://github.com/EpiForeSITE)\n\n# epiworld \u003cimg src=\"assets/branding/epiworld.png\" width=\"200px\" alt=\"epiworld logo\" align=\"right\"\u003e\n\nThis C++ library provides a general framework for epidemiologic simulation. The\ncore principle of `epiworld` is fast epidemiological prototyping for\nbuilding complex models quickly. Here are some of its main features:\n\n  - It only depends on the standard library (C++11 required.)\n  - It is a template library.\n  - It is header-only ([single file](https://github.com/UofUEpiBio/epiworld/tree/master/epiworld.hpp)).\n  - Models can have an arbitrary set of states.\n  - Viruses and tools (e.g., vaccines, mask-wearing) can be designed to have arbitrary features.\n  - Multiple tools and viruses can live in the same simulation.\n  - It is *FAST*: Over 150 Million person/day simulations per second (see example below).\n\nVarious examples can be found in the [examples](https://github.com/UofUEpiBio/epiworld/tree/master/examples) folder. This repository also hosts the `measles` library, which extends `epiworld` with Measles-specific models. The library is available under [`include/measles`](./include/measles/).\n\n## Hello world\n\nHere is a simple SIR model implemented with `epiworld`. The source code\ncan be found [here](https://github.com/UofUEpiBio/epiworld/tree/master/helloworld.cpp), and you can compile the code as follows:\n\n```bash\ng++ -std=c++20 -O3 helloworld.cpp -o helloworld.o\n```\n\nAs you can see in [`helloworld.cpp`](https://github.com/UofUEpiBio/epiworld/tree/master/helloworld.cpp), to use `epiworld` you only need to incorporate the single header file [`epiworld.hpp`](https://github.com/UofUEpiBio/epiworld/tree/master/epiworld.hpp):\n\n```cpp\n#include \"epiworld.hpp\"\n\nusing namespace epiworld;\n\nint main()\n{\n\n    // epiworld already comes with a couple\n    // of models, like the SIR\n    epimodels::ModelSIR\u003c\u003e hello(\n        \"COVID-19\", // Name of the virus\n        0.01,        // Initial prevalence\n        0.1,        // Transmission probability\n        0.3         // Recovery probability\n        );\n\n    // We can simulate agents using a smallworld network\n    // with 100,000 individuals, in this case\n    hello.agents_smallworld(100000, 10L, false, .01);\n\n    // Running the model and printing the results\n    // Setting the number of days (100) and seed (122)\n    hello.run(100, 122);\n    hello.print();\n\n    return 0;\n\n}\n```\n\nCompiling (with `make helloworld.o`) and running the problem yields the following result:\n\n```bash\n_________________________________________________________________________\nRunning the model...\n||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| done.\n________________________________________________________________________________\n________________________________________________________________________________\nSIMULATION STUDY\n\nName of the model   : Susceptible-Infected-Recovered (SIR)\nPopulation size     : 100000\nAgents' data        : (none)\nNumber of entities  : 0\nDays (duration)     : 100 (of 100)\nNumber of viruses   : 1\nLast run elapsed t  : 69.00ms\nLast run speed      : 143.87 million agents x day / second\nRewiring            : off\n\nGlobal events:\n (none)\n\nVirus(es):\n - COVID-19\n\nTool(s):\n (none)\n\nModel parameters:\n - Recovery rate     : 0.3000\n - Transmission rate : 0.1000\n\nDistribution of the population at time 100:\n  - (0) Susceptible :  99000 -\u003e 41957\n  - (1) Infected    :   1000 -\u003e 70\n  - (2) Recovered   :      0 -\u003e 57973\n\nTransition Probabilities:\n - Susceptible  0.99  0.01     -\n - Infected        -  0.70  0.30\n - Recovered       -     -  1.00\n```\n\n\n## Building from scratch\n\nOne of the best things about epiworld is the capability to build models from scratch. Here is one example ([readme.cpp](https://github.com/UofUEpiBio/epiworld/tree/master/readme.cpp)):\n\n```cpp\n#include \"epiworld.hpp\"\n\nusing namespace epiworld;\n\nint main()\n{\n\n    // Creating a model with three statuses:\n    // - Susceptible: Status 0\n    // - Infected: Status 1\n    // - Recovered: Status 2\n    Model\u003c\u003e model;\n    model.add_state(\"Susceptible\", default_update_susceptible\u003c\u003e);\n    model.add_state(\"Infected\", default_update_exposed\u003c\u003e);\n    model.add_state(\"Recovered\");\n\n    // Designing a virus: This virus will:\n    // - Have a 10% transmission rate\n    // - Have a 30% recovery rate\n    // - Infected individuals become \"Infected\" (status 1)\n    // - Recovered individuals become \"Recovered\" (status 2)\n    // 100 individuals will have the virus from the beginning.\n    Virus\u003c\u003e virus(\"covid 19\", 100, false);\n\n    virus.set_prob_infecting(.10);\n    virus.set_prob_recovery(.30);\n    \n    virus.set_state(1, 2);\n\n    model.add_virus(virus);\n    \n    // Generating a random pop from a smallworld network\n    model.agents_smallworld(100000, 10L, false, .01);\n\n    // Running the model\n    model.run(100, 122);\n    model.print();\n  \n}\n```\n\nWhich should print something like the following:\n\n```bash\n_________________________________________________________________________\nRunning the model...\n||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| done.\n________________________________________________________________________________\n________________________________________________________________________________\nSIMULATION STUDY\n\nName of the model   : (none)\nPopulation size     : 100000\nAgents' data        : (none)\nNumber of entities  : 0\nDays (duration)     : 100 (of 100)\nNumber of viruses   : 1\nLast run elapsed t  : 24.00ms\nLast run speed      : 410.34 million agents x day / second\nRewiring            : off\n\nGlobal events:\n (none)\n\nVirus(es):\n - covid 19\n\nTool(s):\n (none)\n\nModel parameters:\n (none)\n\nDistribution of the population at time 100:\n  - (0) Susceptible :  99900 -\u003e 78866\n  - (1) Infected    :    100 -\u003e 625\n  - (2) Recovered   :      0 -\u003e 20509\n\nTransition Probabilities:\n - Susceptible  1.00  0.00     -\n - Infected        -  0.70  0.30\n - Recovered       -     -  1.0\n```\n\nWhich took about 0.024 seconds (~ 401 million agents x day / second).\n\n## Simulation Steps\n\nThe core logic of the model relies on user-defined statuses and their corresponding update functions. In particular, the model does not have a predefined set of statuses, e.g., susceptible, infected, recovered; the user establishes them. This provides flexibility as models in `epiworld` can have an arbitrary set of statuses.\n\nLike most other ABMs, `epiworld` simulates the evolution of a system in discrete steps. Each step represents a day in the system, and changes are reflected at the beginning of the following day. Therefore, agents can recover and transmit a virus on the same day. A single step of `epiworld` features the following procedures:\n\n**Status update**: Agents are updated according to their status.\n\n2. (optional) **Execute Global events**: A call of user-defined functions affecting\nthe system. These can make any type of change in the system.\n\n3. (optional) **Apply rewiring algorithm**: When specified, the network is rewired\naccording to a user-defined function.\n\n4. **Lock the results**: The current date is incremented in one unit, and\n  the changes (exposition, new infections, recoveries, etc.) are recorded\n  in the database.\n\n5. (optional) **Mutate Variants**: When defined, variants can mutate, with the new\nvariants appearing the next day.\n\nTo speed up computations, `epiworld` uses a queuing system that decides which agents will be active during each step and which will not. Agents are active when either they or at least one of their neighbors has a virus active. Agents' updates are triggered only for those in the queue, accelerating the completion of the current step.\n\n## Agents\n\nAgents carry two sets of important information: viruses and tools. Each agent\ncan have multiple instances of them, meaning multiple viruses and tools can\ncoexist in a model. At each step of the simulation, an agent can face the following\nchanges:\n\n- **Acquire a virus (`add_virus()`)**: Become exposed to a particular virus+host.\n\n- **Lose a virus (`rm_virus()`)**: Removing a virus from the agent. Losing a virus\ntriggers a call to the virus's `postrecovery()` function, which can, for example,\nresult in gaining immunity to that variant.\n\n- **Acquire a tool (`add_tool()`)**: For example, mask-wearing, vaccines, etc.\n\n- **Lose a tool (`rm_tool()`)**: For example, stop wearing masks, lose immunity, etc.\n\n- **Change status (`change_status()`)**: An arbitrary change in the status of the\nagent. Examples of this are moving from \"exposed\" to \"infected,\" from \"infected\"\nto \"ICU,\" etc.\n\nAny action in the model can trigger a change in its queuing system. By default, becoming exposed makes the agent (and its neighbors) active in the queuing system. Likewise, losing all viruses could make the agent and its neighbors inactive.\n\n\u003c!--\n## Tools --\u003e\n\n## Contagion\n\nSusceptible individuals can acquire a virus from any of their infected connections. The probability that susceptible individual `i` gets the virus `v` from individual `j` depends on how three things:\n\n1. The transmissibility of the virus, \u003c!-- $P_v \\in [0,1]$ --\u003e \u003cimg style=\"transform: translateY(0.1em); background: white;\" src=\"https://latex.codecogs.com/svg.latex?P_v%20%5Cin%20%5B0%2C1%5D\"\u003e,\n2. The contagion reduction factor of `i`, \u003c!-- $C_r \\in [0,1]$ --\u003e \u003cimg style=\"transform: translateY(0.1em); background: white;\" src=\"https://latex.codecogs.com/svg.latex?C_r%20%5Cin%20%5B0%2C1%5D\"\u003e, and\n3. The host's transmission reduction factor, \u003c!-- $T_r \\in [0,1]$ --\u003e \u003cimg style=\"transform: translateY(0.1em); background: white;\" src=\"https://latex.codecogs.com/svg.latex?T_r%20%5Cin%20%5B0%2C1%5D\"\u003e.\n\nThe last two are computed from \u003c!-- $i$ --\u003e \u003cimg style=\"transform: translateY(0.1em); background: white;\" src=\"https://latex.codecogs.com/svg.latex?i\"\u003e and \u003c!-- $j$ --\u003e \u003cimg style=\"transform: translateY(0.1em); background: white;\" src=\"https://latex.codecogs.com/svg.latex?j\"\u003e's tools. Ultimately, the probability of \u003c!-- $i$ --\u003e \u003cimg style=\"transform: translateY(0.1em); background: white;\" src=\"https://latex.codecogs.com/svg.latex?i\"\u003e getting virus $v$ from \u003c!-- $j$ --\u003e \u003cimg style=\"transform: translateY(0.1em); background: white;\" src=\"https://latex.codecogs.com/svg.latex?j\"\u003e equals:\n\n\u003c!-- $$\nP(Virus v) = P_v * (1 - C_r) *(1 - T_r)\n$$ --\u003e\n\n\u003cdiv align=\"center\"\u003e\u003cimg style=\"background: white;\" src=\"https://latex.codecogs.com/svg.latex?P(Virus%20v)%20%3D%20P_v%20*%20(1%20-%20C_r)%20*(1%20-%20T_r)%20\"\u003e\u003c/div\u003e\n\nNonetheless, the default behavior of the simulation model is to assume that individuals can acquire only one disease at a time, if any. This way, the actual probability is:\n\n\u003c!-- $$\nP(Virus v|\\mbox{\\text{at most one virus}}) = P_{ivj}\n$$ --\u003e\n\n\u003cdiv align=\"center\"\u003e\u003cimg style=\"background: white;\" src=\"https://latex.codecogs.com/svg.latex?P(Virus%20v%20%7C%20%5Cmbox%7Bat%20most%20one%20virus%7D)%20%3D%20P_%7Bivj%7D\"\u003e\u003c/div\u003e\n\nThe latter is calculated using Bayes' rule\n\n\u003c!-- $$\n\\begin{align*}\nP_{ivj} \u0026 = P(\\text{at most one virus}|\\text{Virus v}) * P_v / P(\\text{at most one virus}) \\\\\n        \u0026 = P(\\text{Only Virus v})/P_v * P(\\text{Virus v}) / P(\\text{at most one virus}) \\\\\n        \u0026 = P(\\text{Only Virus v})/P(\\text{at most one virus})\n\\end{align*}\n$$ --\u003e\n\n\u003cdiv align=\"center\"\u003e\u003cimg style=\"background: white;\" src=\"https://latex.codecogs.com/svg.latex?%5Cbegin%7Balign%2A%7D%0AP_%7Bivj%7D%20%26%20%3D%20P%28%5Ctext%7Bat%20most%20one%20virus%7D%7C%5Ctext%7BVirus%20v%7D%29%20%2A%20P_v%20%2F%20P%28%5Ctext%7Bat%20most%20one%20virus%7D%29%20%5C%5C%0A%20%20%20%20%20%20%20%20%26%20%3D%20P%28%5Ctext%7BOnly%20Virus%20v%7D%29%2FP_v%20%2A%20P%28%5Ctext%7BVirus%20v%7D%29%20%2F%20P%28%5Ctext%7Bat%20most%20one%20virus%7D%29%20%5C%5C%0A%20%20%20%20%20%20%20%20%26%20%3D%20P%28%5Ctext%7BOnly%20Virus%20v%7D%29%2FP%28%5Ctext%7Bat%20most%20one%20virus%7D%29%0A%5Cend%7Balign%2A%7D\"\u003e\u003c/div\u003e\n\n\nWhere\n\n\u003c!-- $$\n\\begin{align*}\nP(\\text{Only Virus V})      \u0026 = P_v * \\prod_{m!=V} (1 - P_m) \\\\\nP(\\text{at most one virus}) \u0026 = P(None) + \\sum_{k \\in \\text{viruses}} P_k * \\prod_{m != k} (1 - P_m) \\\\\nP(\\text{None})              \u0026 = \\prod_{k \\in \\text{viruses}} (1 - P_k)\n\\end{align*}\n$$ --\u003e\n\n\u003cdiv align=\"center\"\u003e\u003cimg style=\"background: white;\" src=\"https://latex.codecogs.com/svg.latex?%5Cbegin%7Balign%2A%7D%0AP%28%5Ctext%7BOnly%20Virus%20V%7D%29%20%20%20%20%20%20%26%20%3D%20P_v%20%2A%20%5Cprod_%7Bm%21%3DV%7D%20%281%20-%20P_m%29%20%5C%5C%0AP%28%5Ctext%7Bat%20most%20one%20virus%7D%29%20%26%20%3D%20P%28%5Ctext%7BNone%7D%29%20%2B%20%5Csum_%7Bk%20%5Cin%20%5Ctext%7Bviruses%7D%7D%20P_k%20%2A%20%5Cprod_%7Bm%20%21%3D%20k%7D%20%281%20-%20P_m%29%20%5C%5C%0AP%28%5Ctext%7BNone%7D%29%20%20%20%20%20%20%20%20%20%20%20%20%20%20%26%20%3D%20%5Cprod_%7Bk%20%5Cin%20%5Ctext%7Bviruses%7D%7D%20%281%20-%20P_k%29%0A%5Cend%7Balign%2A%7D\"\u003e\u003c/div\u003e\n\nThis way, viruses with higher transmissibility will be more likely to be acquired when competing with other variants.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuofuepibio%2Fepiworld","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuofuepibio%2Fepiworld","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuofuepibio%2Fepiworld/lists"}