Agent-based supply chain simulation for the PROVIDER research project (BMBF-funded, OFFIS e.V.).
Models the global soya supply chain from Brazilian/US farms through wholesalers, sea transport, EU processors, and feed manufacturers to EU livestock farms. Scenarios apply KG-derived shock parameters (drought, port capacity, input price shocks) and observe emergent price and sourcing behaviour across the chain.
Built on Melodie (Python ABM framework).
simenv/
├── pyproject.toml
└── src/
└── provider_simenv/
├── main.py ← entry point
├── model.py ← simulation orchestrator
├── scenario.py ← all scenario parameters
├── environment.py ← global state + price aggregation
├── data_collector.py ← Melodie output registration
├── tick_writer.py ← per-tick PostgreSQL writer
├── db_config.py ← PostgreSQL connection config
├── visualize_sql.py ← plots from SQLite (post-run)
├── visualize_csv.py ← plots from CSV (fallback)
├── agents/
│ ├── farmer.py ← BRA / USA / EU farmers
│ ├── trader.py ← wholesalers + feed traders
│ ├── transport.py ← land + sea transport operators
│ └── process.py ← processors + feed manufacturers
└── data/
├── input/
│ └── SimulatorScenarios.csv ← scenario definitions
└── output/ ← generated at runtime
├── Result_Simulator_*.csv
├── provider-simenv.sqlite
├── price_curves.png
└── volume_flow.png
Python: 3.10 or higher
Required:
Melodie>=0.6.0
pandas
numpy
matplotlib
pyyaml
Optional — only needed for PostgreSQL output:
sqlalchemy
psycopg2-binary
If sqlalchemy / psycopg2-binary are not installed, the tick writer disables itself
silently and the simulation continues normally. CSV and SQLite outputs are unaffected.
# Create and activate a virtual environment
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate
# Install core dependencies (run in project root)
pip install .
# Optional: Install all packages needed for development (run in project root)
pip install '.[dev]'
# This should ususally be done in editable mode for development purposes:
pip install -e '.[dev]'
# Optional: Install with PostgreSQL support (run in project root)
pip install '.[db]'# Navigate to the simulation package — Melodie resolves data/ paths from here
cd src/provider_simenv
# Run
python main.pyThe simulation reads scenarios from data/input/SimulatorScenarios.csv, runs all scenarios
in sequence, and writes output to data/output/.
What runs automatically:
- Simulation loop — all scenarios, 52 steps each, per-tick stdout
- Per-tick PostgreSQL writes via
tick_writer.py(if Postgres is reachable; silent skip otherwise) - Post-run: CSV → SQLite merge →
provider-simenv.sqlite
# From src/provider_simenv/
# Recommended: plots from SQLite — price curves + BRA/USA volume flow
python visualize_sql.py
# Fallback: plots from CSV
python visualize_csv.pyOutput PNGs are saved to data/output/.
Scenarios are defined in data/input/SimulatorScenarios.csv. Each row is one scenario run.
| Parameter | Effect |
|---|---|
farm_capacity_bra |
BRA farm output multiplier — 1.0 = normal, 0.7 = 30% drought loss |
port_capacity_sa |
SA export port throughput multiplier |
fertilizer_price_factor |
Multiplier on BRA farmer fixed costs (GTA Red interventions) |
energy_price_factor |
Multiplier on all transport fixed costs |
oil_mill_capacity |
EU processor output multiplier |
feed_mill_capacity |
Feed manufacturer output multiplier |
shock_onset_step |
Step at which shock starts ramping in |
shock_ramp_steps |
Steps to ramp from baseline to full shock value |
wholesaler_storage_capacity |
Max tonnes a wholesaler can hold per step (default: 20 000 t) |
usa_surplus_factor |
USA idle capacity multiplier — 1.5 = 50% reserve above base yield |
period_num |
Number of simulation steps (default: 52) |
The simulation can also be run in a docker container. First, build the container. In the repo root run
docker build -t provider-simenv .Then you can run the simulation in the container with
docker run --rm -v <path to pdl file directory>:/scenarios provider-simenv --pdl /scenarios/<pdl filename>You can also configure a PostgreSQL interface for data storage (see next chapter) with
docker run --rm -v <path to pdl file directory>:/scenarios provider-simenv --pdl /scenarios/<pdl filename> --postgres-url <PostgreSQL URL string>PostgreSQL enables live data access during the simulation — required for future palaestrAI integration. Without it, everything works via CSV + SQLite.
docker run --name provider-postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_DB=provider_simenv -p 5432:5432 -d postgres:16These credentials match the defaults in db_config.py. No further configuration needed.
To persist data across container restarts, add a volume:
docker run --name provider-postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_USER=postgres -e POSTGRES_DB=provider_simenv -p 5432:5432 -v pgdata:/var/lib/postgresql/data -d postgres:16| Field | Default |
|---|---|
| host | localhost |
| port | 5432 |
| dbname | provider_simenv |
| user | postgres |
| password | postgres |
Override by constructing PostgresDBConfig with different values or passing env vars at runtime.
-- Should return 3 rows, each COUNT = 52 (for a 3-scenario, 52-step run)
SELECT id_scenario, COUNT(*)
FROM "Result_Simulator_Environment"
GROUP BY id_scenario
ORDER BY id_scenario;Result_Simulator_Environment
Result_Simulator_BraFarmers
Result_Simulator_UsaFarmers
Result_Simulator_Wholesalers
Result_Simulator_Processors
Result_Simulator_FeedManufacturers
Result_Simulator_FeedTraders
Result_Simulator_EuFarmers
Tables are dropped and recreated at the start of each full simulation run (first scenario only). Subsequent scenarios within the same run append to the existing tables.
You can also run a docker compose that sets up a PostgreSQL database and links it to the simulation container. Using our helper script, everything is configured automatically. Just run
./compose-up.sh <path to pdl file>from the repository root. This builds the database container, if it's not already up and runs a simulation of the specified pdl file. You can run different configurations by simply repeating this call with the respective paths.
| File | Description |
|---|---|
data/output/Result_Simulator_*.csv |
Raw per-agent per-step output written by Melodie |
data/output/provider-simenv.sqlite |
All CSVs merged into one SQLite database (post-run) |
data/output/price_curves.png |
Soja + feed price development across all scenarios |
data/output/volume_flow.png |
BRA vs USA sourcing volumes per scenario |
- Run from
src/provider_simenv/— Melodie resolvesdata/paths relative to the working directory. Running from the repo root will fail to find input files. - Melodie SQLite mode is disabled —
data_output_type="sqlite"silently drops all rows due to a missingconn.commit()in SQLAlchemy 2.0. Thecsv_to_sqlite()function inmain.pyis used instead and called automatically. run_stepwise()inmodel.pyis the designated integration hook for external control (e.g. palaestrAI). It yields a state dict{step, shock_scale, soja_price, feed_price, ...}after every simulation step.
PROVIDER — AI-based supply chain resilience simulation
OFFIS e.V. – Institut für Informatik, Oldenburg
BMBF-funded