Attack Graph driven Discrete Event Simulation for Security Assessment in Power Systems — Artifacts - ACM SIGSIM PADS 2026
Repository for running Control Finite State Machine-based simulations in OMNeT++ and learning Dynamic Bayesian Network (DBN) parameters from generated data traces.
The results reproduced by this repository are reported in the paper: "Attack Graph driven Discrete Event Simulation for Security Assessment in Power Systems"
Accepted at ACM SIGSIM PADS 2026, June 24-26, 2026, Vienna, Austria.
- Davide Savarro (corresponding author) → davide.savarro@unito.it
- Davide Cerotti → davide.cerotti@uniupo.it
- Daniele Codetta Raiteri → daniele.codetta@uniupo.it
- Lavinia Egidi → lavinia.egidi@uniupo.it
- Giuliana Franceschinis → giuliana.franceschinis@uniupo.it
- Luigi Portinale → luigi.portinale@uniupo.it
- Giovanna Dondossola → giovanna.dondossola@rse-web.it
- Roberta Terruggia → roberta.terruggia@rse-web.it
Using the provided Dockerfile, you can build a container that includes all necessary dependencies to run the full pipeline (simulation, parameterization, validation, and analysis). Setting up the simulation environment manually can impact the automatic replicability of the results due to possible configuration differences, so using Docker is the recommended approach.
- x86_64 CPU architecture
- 32 GB of RAM
- At least 20 GB of free disk space for the container, simulation outputs, and results
- Linux system with Docker,
sudo,bashandgitinstalled (see the specific versions we used below)
Note
In this README we assume that you need to acquire superuser privileges (using sudo) to run Docker commands; if your setup uses the docker group/rootless Docker, manually remove sudo from the commands
Hardware Specifications:
- OS: Ubuntu 22.04.5 LTS (Jammy)
- Kernel: 5.15.0-164-generic
- CPU: Intel(R) Xeon(R) Gold 6418H (32 logical cores @2.10GHz)
- RAM: 64 GB (swap: 8 GB)
Software Specifications:
- Sudo: 1.9.9
- GNU Bash: 5.1.16
- Git: 2.34.1
- Docker Client & Server Engine: 28.2.2
- Docker buildx: 0.21.3
git clone --recurse-submodules https://github.com/Dosclic98/dbn-sim-learning.git
cd dbn-sim-learningNote
All scripts were tested by running them from the following path: dbn-sim-learning/.
If you downloaded the repository as a ZIP or tar.gz file, make sure to extract it with the full folder structure intact.
This repository includes a git submodule under MQTT_MMS_Medium/, which contains the OMNeT++ simulation model executed by the experiments.
If you did not clone with submodules, initialize them with:
git submodule update --init --recursiveYou need a BayesFusion SMILE/pysmile Academic license.
-
Navigate to the BayesFusion support page and log in or create an account using your academic email.
-
Request an Academic license by clicking on the following button in the SMILE section:
-
Fill in the form specifying your academic institution and ticking the necessary checkboxes, then click the "Get License" button.
-
Unzip the archive that will be immediately downloaded and locate the
pysmile_license.pyfile inside it and insert thepysmile_license.pyfile in the repository root.
dbn-sim-learning/
├── docker/
├── models/
├── plots/
├── results/
├── traces/
├── MQTT_MMS_Medium/
├── LICENSE
├── README.md
├── pysmile_license.py <-- insert your pysmile_license.py here
├── ...
Using the helper script:
./buildContainer.shOr manually:
sudo docker buildx build --progress=plain -t omnet ./docker/Warning
A stable internet connection is required during the build process to download the OMNeT++ source and all other dependencies. The build process may take around 5-10 minutes depending on your connection speed and host performance.
If you are behind a firewall/proxy, ensure outbound HTTPS access to at least these endpoints:
github.com(repository clone, submodules, release metadata)objects.githubusercontent.com(release assets)pypi.org(main index for python packages)support.bayesfusion.com(pysmile package index)
Using the helper script:
./runContainer.shOr manually (shares plots/, results/, traces/ folders on the host):
mkdir -p dbn-sim-learning-container/{plots,results,traces}
sudo docker run --rm -it \
-v "$PWD/pysmile_license.py":/home/simulation/dbn-sim-learning/pysmile_license.py:ro \
-v "$PWD/dbn-sim-learning-container/plots":/home/simulation/dbn-sim-learning/plots \
-v "$PWD/dbn-sim-learning-container/results":/home/simulation/dbn-sim-learning/results \
-v "$PWD/dbn-sim-learning-container/traces":/home/simulation/dbn-sim-learning/traces \
omnetFrom /home/simulation/dbn-sim-learning (container workdir), run:
./replicateResults.shThis script, by calling replicate_results.py, will:
- run the simulation batch and trace aggregation (via
runSimulation.py) with 1000 runs and using all but 2 of the available cores for parallelization - run
parameterizer.pyin normal and benchmark mode - run
data_evaluator.py - run
experiment_analyzer.pyin normal and benchmark mode - run
validator_playground.py - print the total wall-clock time at the end
The full pipeline (simulation, parameterization, validation, and analysis) takes approximately 2 hours and 15 minutes on the reference host, with 1000 traces and using 30 cores for parallelization. The exact time may vary based on the host specifications. The most time-consuming step is the validation since the DBN must be retrained and tested multiple times for every fold and for every evidence frequency.
The following table maps the paper elements (figures, tables and sections) to the files generated on the host under dbn-sim-learning-container/.
| Paper element | Generated file(s) under dbn-sim-learning-container/ |
Notes |
|---|---|---|
| Figure 5 | plots/completion_slice_distribution.pdf |
Produced by data_evaluator.py. |
| Figure 6 | plots/No evidence_targetNodes_Completed.pdf |
Produced by experiment_analyzer.py. |
| Figure 7 | plots/validation_metrics_vs_evEveryNSlices.pdf |
Produced by validator_playground.py. |
| Table 2 | results/simulation_resources_summary.csvresults/parameter_learning_benchmark_aggregated.csvresults/benchmark_inference_times.csv |
Aggregated simulation, parameter-learning, and inference benchmark summaries. |
| Entropy analysis (Section 5.2) | results/node_entropy_values.csvresults/node_entropy_summary.csv |
Produced by data_evaluator.py; both per-node and average + std entropy values are reported. |
The originally submitted plots and results are in the same paths mentioned in the table but in the root of the repository (e.g., plots/completion_slice_distribution.pdf).
Warning
Time and resource usage may vary based on the host specifications and current load. The values provided in Table 2 are based on the reference host described above, but actual results may differ on different hardware or under different conditions.
This repository is currently organized around a small set of Python entrypoints in the repository root.
When running via Docker, outputs inside the container are written to plots/, results/, and traces/ and are bind-mounted to the host under dbn-sim-learning-container/{plots,results,traces} (see the docker/ folder and runContainer.sh).
Run:
python3 replicate_results.py -r 1000 -p "$(nproc)"replicate_results.py runs the whole pipeline in sequence:
runSimulation.py(simulation batch + resource monitoring)parameterizer.py(single learning run)parameterizer.py --bench(parameter-learning benchmark)data_evaluator.py(trace distribution + entropy)experiment_analyzer.py(inference plots)experiment_analyzer.py --bench(inference benchmark)validator_playground.py(k-fold validation vs evidence frequency)
It also ensures plots/, results/, and traces/ exist before starting.
Run:
python3 runSimulation.py -r 1000 -p 30It is designed to run inside the container where OMNeT++ is installed.
It launches multiple OMNeT++ runs in parallel and monitors per-run wall-clock time and peak RSS (requires psutil).
After all runs complete, it calls the simulator's aggregator.sh to produce the aggregated trace CSV.
Main outputs:
results/logger.log: simulator + aggregation logsresults/simulation_resources.csv: per-run wall-clock and peak RSSresults/simulation_resources_summary.csv: mean/std of wall-clock and peak RSSresults/dbnLogs.csvandtraces/dbnLogs.csv: aggregated traces used by the learning/analysis scripts
Defaults (edit at the top of the script if you need to change them):
- Input model:
models/DBNfromAG.xdsl - Output model:
models/DBNfromAG_learned.xdsl - Traces:
traces/dbnLogs.csv - Slices:
numSlices = 100
Run a single learning pass:
python3 parameterizer.pyRun the benchmark (repeats learning multiple times and records time/RAM via tracemalloc):
python3 parameterizer.py --benchBenchmark outputs:
results/parameter_learning_benchmark.csvresults/parameter_learning_benchmark_aggregated.csv
This script loads models/DBNfromAG_learned.xdsl and runs the experiments defined in-code (currently an example with the single experiment named No evidence).
By default it uses EPIS sampling (algoTypeExact = False); set algoTypeExact = True for the exact Lauritzen algorithm.
Run inference + generate the posterior plot:
python3 experiment_analyzer.pyOutput:
plots/No evidence_targetNodes_Completed.pdf
Run the inference benchmark (repeat runs + aggregate avg/std time and peak RAM):
python3 experiment_analyzer.py --benchBenchmark output:
results/benchmark_inference_times.csv
validator.py contains the Validator class implementing 5-fold CV over the trace dataset.
validator_playground.py wires it together for the experiment used in this project:
- uses
models/DBNfromAG_learned.xdsl - performs 5-folds CV on
traces/dbnLogs.csvvarying the evidence frequency viaext_ev_every_n_slices = [1, 2, 5, 10]
Run validation (computes and stores CSVs):
python3 validator_playground.pyLoad already-computed CSVs and only re-generate the plot:
python3 validator_playground.py --storedOutputs:
results/5_folds-evEveryNSlices_*.csvresults/5_folds-full_results.csvplots/validation_metrics_vs_evEveryNSlices.pdf
This script analyzes traces/dbnLogs.csv to:
- plot completion-slice histograms for selected target nodes
- compute per-node entropy of completion-slice distributions and export them to CSV
Run:
python3 data_evaluator.pyOutputs:
plots/completion_slice_distribution.pdfresults/node_entropy_values.csvresults/node_entropy_summary.csv
This repository is licensed under the GNU General Public License v3.0 (GPL-3.0). See the LICENSE file for details.

