The simulator is organized as a modular C++ project with clear separation of concerns. New policies and distributions can be added without modifying core code.
The project follows the Pitchfork Layout convention for directory organisation.
The project follows these key principles:
mjqm-{component} prefixes to avoid name collisionsmjqm-simulator
├── docs
├── Inputs
│ └── {your_and_default_input_files...}
├── libs
│ ├── policies
│ │ ├── include
│ │ │ └── mjqm-policies
│ │ │ ├── policies.h
│ │ │ ├── policy.h
│ │ │ └── {SpecificPolicy...}.h
│ │ ├── src
│ │ │ └── mjqm-policies
│ │ │ └── {SpecificPolicy...}.cpp
│ │ └── CMakeLists.txt
│ ├── samplers
│ │ ├── include
│ │ │ └── mjqm-samplers
│ │ │ ├── sampler.h
│ │ │ ├── samplers.h
│ │ │ └── {specific_sampler...}.hpp
│ │ └── CMakeLists.txt
│ ├── simulator
│ │ ├── include
│ │ │ ├── mjqm-settings
│ │ │ │ ├── toml_distributions_loaders.h
│ │ │ │ ├── toml_loader.h
│ │ │ │ ├── toml_overrides.h
│ │ │ │ ├── toml_policies_loaders.h
│ │ │ │ └── toml_utils.h
│ │ │ └── mjqm-simulator
│ │ │ ├── experiment.h
│ │ │ ├── experiment_stats.h
│ │ │ ├── simulator.h
│ │ │ └── stats.h
│ │ ├── src
│ │ │ ├── mjqm-settings
│ │ │ │ ├── toml_distributions_loaders.cpp
│ │ │ │ ├── toml_loader.cpp
│ │ │ │ ├── toml_overrides.cpp
│ │ │ │ ├── toml_policies_loaders.cpp
│ │ │ │ └── toml_utils.cpp
│ │ │ └── mjqm-simulator
│ │ │ └── experiment_stats.cpp
│ │ └── CMakeLists.txt
│ └── utils
│ ├── include
│ │ ├── mjqm-math
│ │ │ └── confidence_intervals.h
│ │ └── mjqm-utils
│ │ └── string.hpp
│ ├── src
│ │ └── mjqm-math
│ │ └── confidence_intervals.cpp
│ └── CMakeLists.txt
├── scripts
│ ├── convert_conf.py
│ ├── ensure_same_results.py
│ └── select-g++.sh
├── test
│ └── expected
│ └── {expected-output-files...}
├── CMakeLists.txt
├── CMakePresets.json
├── configure
├── README.md
├── rebuild
├── simulator.cpp
└── toml_loader_test.cpp
The project is organized in the following way:
docs/: Contains the documentation of the project.Inputs/: Contains the input files for the simulator. In the repository, only the input files for the tests are included.libs/: Contains the high level libraries used in the project.
Each high level library has its own folder with the following structure:
CMakeLists.txt: Contains the CMake configuration for the library.include/: Contains the header files of the library.
This folder is organized in subfolders for each logical module of the library.
The whole include/ folder is included in the root CMakeLists.txt, so the headers are available to the whole project via names as mjqm-{logical_module}/.... This achieves explicit separation of our code from external libraries.src/: Contains the source files of the library.
Usually, each source file should be included in the CMakeLists.txt of the library.libs/policies/: Contains the specific policies used in the simulator.
Each policy has its own header and source file. The latter should be included in the CMakeLists.txt policies target.
The policies.h file includes all the policies headers files for easier inclusion.libs/samplers/: Contains the distributions implementation for sampling.
Each sampler has its own header file that directly define the implementation.
The samplers.h file includes all the samplers headers files for easier inclusion.libs/simulator/: Contains the actual simulator code and its settings loader.
For a cleaner organization, the loaders for distributions and policies are separated.libs/utils/: Contains some string and math utilities.scripts/: Contains some scripts for solving small tasks running the project.
convert_conf.py: Converts the configuration files from the two-file logic to the TOML format.ensure_same_results.py: Checks if the results of two simulations are the same.test/expected/: Contains the expected output files for the tests.The libraries have the following dependency structure:
simulator (top-level application)
├── depends on: policies
├── depends on: samplers
└── depends on: utils
policies
└── depends on: (none, pure interface)
samplers
└── depends on: (none, pure interface)
utils
└── depends on: (none, pure utilities)
This dependency hierarchy ensures:
All scheduling policies implement the Policy interface defined in libs/policies/include/mjqm-policies/policy.h. This interface defines:
arrival() and departure() methods called by the simulatorflush_buffer() method containing the core scheduling algorithmSee Policies for detailed implementation guidance.
All service time and inter-arrival time distributions implement the DistributionSampler interface in libs/samplers/include/mjqm-samplers/sampler.h. This interface defines:
sample() method to generate random variatesget_mean() and get_variance() for theoretical momentsclone() method for independent experiment runsSee Distributions for detailed implementation guidance.
The TOML configuration system uses a loader pattern with builder functions:
toml_distributions_loaders.cpp): Read distribution parameters, validate, construct sampler instancestoml_policies_loaders.cpp): Read policy parameters, validate, construct policy instancesThis pattern allows adding new policies and distributions by:
No changes to core simulation engine required.
The simulator provides several extension points:
Add to libs/policies/:
Policy interfacepolicy_builders mapAdd to libs/samplers/:
DistributionSampler interfacedistribution_loaders mapSee: Implementing distributions
Modify libs/simulator/include/mjqm-simulator/experiment_stats.h to:
Add Python scripts to scripts/ directory:
load_experiment_data.py module to read results./configure # First time: configures CMake and Python environment
# After modifying code
./rebuild # Recompiles changed files
# After modifying code with detailed debugging
./rebuild --debug # Rebuild with debug symbols
# After major changes (CMakeLists.txt, dependencies)
./configure --clean # Full rebuild from scratch
./rebuild
./configure --test # Configure and run tests
./rebuild --test # Rebuild and run tests
Tests are defined in CMakeLists.txt and compare outputs against expected results in test/expected/.
.h): Interface declarations for non-template code.hpp): Header-only implementations (samplers).cpp): Implementation files.toml): Experiment configurations.py): Analysis and utility scriptsSmash policy or Exponential distribution