Skip to content

Library Architecture

Introduction

The epiworld library is structured around a modular architecture that models populations, interactions, and dynamics in epidemiological simulations. At its core, the Agent class represents individuals, encapsulating their state, relationships, and associated tools or viruses. Agents interact with one another through defined neighbors, which are managed as adjacency lists, and their states can change based on interactions or external events. The Entity class organizes agents into groups, facilitating structured interactions and shared attributes, with entities being managed by the Model class. The Model class serves as a coordinator, maintaining the population of agents, entities, and the simulation's global parameters, such as random number generators and contact matrices. Events, represented as functions, define actions that modify agent states, introduce new tools or viruses, or adjust global parameters. The library uses templates extensively, allowing sequence types and other components to be customized for specific simulation needs. Data collection and analysis are integrated through the DataBase class, which records transmissions, state transitions, and other metrics for post-simulation analysis. This allows the logical separation of concerns as they relate to agent-level logic, group-level dynamics, and global simulation control. Each component operates independently while interacting through well-defined interfaces.

Overview of File Organization

Directory Description
include/ Header files for the core of epiworld, and vendored libraries
examples/ Example models and usage demonstrations
tests/ Unit or integration tests
benchmark/ Performance benchmarks
docs/ User documentation, model descriptions, perhaps architecture notes
epiworld.hpp The pre-built, pre-packaged "monoheader" for epiworld.
There are files at the root of the repository (e.g. Makefile, Doxyfile), but these should be mostly self explanatory, and/or stock. Usage is header-only, with template-based implementations in epiworld.hpp (or in files under include/). The library depends only on the C++ standard library (since it is a header-only template library); the cxxopt and catch2 libraries are used in the examples and unit tests (which are not required under normal operation).

Bones and Meat

In the epiworld codebase, "bones and meat" refers to a strict separation between the public interface and the implementation, even though the project is header-only. The bones are the minimal, stable declarations that define how users interact with the library: class and struct definitions, public method signatures, type aliases, constants, and lightweight inline adapters. These appear in the top-level headers that users include directly. They are intentionally compact and readable so the API surface is obvious, navigable, and unlikely to change frequently.

The meat is the implementation that realizes those interfaces. Because the project is header-only, the meat also lives in headers, but it is kept apart from the interface. This includes method bodies, helper templates, algorithmic kernels, and any internal utilities that are not part of the supported API. Users include the bones (or even, ideally, just the root epiworld.cpp); the meat is pulled in transitively but is not intended to be referenced directly.

This separation has a few practical effects. API stability and documentation focus on the bones, keeping the public surface small and predictable. The implementation can evolve—optimize algorithms, refactor helpers, add specializations—without breaking user code, as long as the bones remain consistent. Build behavior also benefits: declarations compile quickly, while the heavier template and inline definitions are isolated to implementation sections, reducing incidental coupling and making diffs and reviews more targeted.