Digital Multi-Level Assembly (MLA) manufacturing factory simulation made with SimPy
Project description
mlafactory
mlafactory is an open-source discrete-event simulation framework for modeling Multi-Level Assembly (MLA) manufacturing systems. Built on top of SimPy, it enables flexible simulation of factories with dynamic inventory management, heterogeneous machine pools, stochastic order arrivals, and configurable production and replenishment policies.
The framework is designed for research, experimentation, and reproducible evaluation of manufacturing strategies.
Features
- Multi-level bill of materials (BOM) — recursive assembly of products from sub-components and raw materials
- Heterogeneous machine pools — multiple machine types with configurable setup times, cycle times, and costs
- Dynamic inventory management — min/max stock policies with async waiting and automatic replenishment
- Stochastic order arrivals — fixed, random, spread, or distribution-based inter-order intervals
- Configurable replenishment — per-component reorder delays for raw materials
- Multiple inventory initialization strategies — zero, min, max, or random initial stock levels
- Rich reporting — production service levels, machine utilization, and inventory summaries exported as CSV
- CLI and Python API — run simulations without writing code or integrate programmatically
- YAML / JSON configuration — fully reproducible experiments via configuration files
Requirements
- Python 3.9+
- SimPy >= 4.0
- pandas
- PyYAML
Installation
pip install mlafactory
Install from source:
git clone https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory.git
cd mla_factory
pip install -e .
Quick Start
Command Line
mlafactory ships with a built-in bike factory example:
mlafactory --show-output
To run with a custom configuration file:
mlafactory --factory-config my_factory.yml --show-output
Python API
from mlafactory.FactoryRunner import FactoryRunner
# Load from a configuration file
simulator = FactoryRunner.from_config("my_factory.yml")
result = simulator.run()
# Or configure programmatically
simulator = FactoryRunner(
factory_name="BikeFactory",
bom=bom,
initial_inventory=initial_inventory,
reorder_delays=reorder_delays,
product_demand=product_demand,
machines=machines,
stock_limits=stock_limits,
months=12,
hours_per_month=160,
inventory_strategy="max",
show_output=True,
export_reports=True,
output_dir="output/",
)
result = simulator.run()
Expected Output
Elapsed real time: 0.02940058708190918
Total simulated time: 1920 hours
======================================== Production Results ========================================
product demand fulfilled inventory production fulfillment_ratio production_ratio
0 RoadBike 52 26 6 32 0.500000 0.615385
1 MountainBike 65 57 6 63 0.876923 0.969231
2 ElectricBike 63 28 3 31 0.444444 0.492063
3 TOTAL 180 111 15 126 0.616667 0.692226
======================================== Machines Summary ========================================
type name setup_time cycle_time n_setups n_cycles setup_cost cycle_cost tt_setup tt_build tt_idle
0 bike bk01 1.0 25.0 13 32 0 0.0 0.216667 13.333333 1906.450000
1 bike bk02 2.0 20.0 13 32 0 0.0 0.433333 10.666667 1908.900000
2 bike bk03 3.0 19.0 14 31 0 0.0 0.700000 9.816667 1909.483333
3 bike bk04 4.0 17.0 14 31 0 0.0 0.933333 8.783333 1910.283333
4 frame fr01 2.0 15.0 3 43 0 0.0 0.100000 10.750000 1909.150000
5 frame fr02 3.0 12.0 2 39 0 0.0 0.100000 7.800000 1912.100000
6 frame fr03 3.0 13.0 3 39 0 0.0 0.150000 8.450000 1911.400000
7 frame fr04 4.0 14.0 2 53 0 0.0 0.133333 12.366667 1907.500000
8 wheel wl01 3.0 8.0 29 43 0 0.0 1.450000 5.733333 1912.816667
9 wheel wl02 10.0 5.0 29 43 0 0.0 4.833333 3.583333 1911.583333
10 wheel wl03 1.0 10.0 4 42 0 0.0 0.066667 7.000000 1912.933333
11 wheel wl04 2.0 7.0 4 42 0 0.0 0.133333 4.900000 1914.966667
12 wheel wl05 9.0 6.0 4 42 0 0.0 0.600000 4.200000 1915.200000
13 wheel wl06 3.0 5.0 4 42 0 0.0 0.200000 3.500000 1916.300000
======================================== Inventory Summary ========================================
item initial consumed final n_reorders
0 MountainBike 0.0 57.0 6.0 NaN
1 RoadBike 0.0 26.0 6.0 NaN
2 ElectricBike 0.0 28.0 3.0 NaN
3 wheel_a 0.0 126.0 1.0 NaN
4 wheel_b 0.0 126.0 1.0 NaN
5 frame_a 0.0 97.0 27.0 NaN
6 frame_b 0.0 32.0 18.0 NaN
7 pedal 10.0 258.0 16.0 22.0
8 crank_arm 5.0 129.0 13.0 22.0
9 front_derailleur 4.0 129.0 12.0 22.0
10 chain 3.0 129.0 12.0 22.0
11 chain_rings 2.0 129.0 12.0 22.0
12 rear_brakes 1.0 129.0 12.0 22.0
13 cogset 2.0 129.0 12.0 22.0
14 rear_derailleur 3.0 129.0 12.0 22.0
15 spokes 25.0 6350.0 10.0 127.0
16 hub 1.0 256.0 17.0 24.0
17 rim 1.0 256.0 17.0 24.0
18 tire 1.0 256.0 17.0 24.0
19 valve 1.0 256.0 17.0 24.0
20 top_tube 1.0 174.0 14.0 10.0
21 down_tube 1.0 174.0 14.0 10.0
22 seat_tube 1.0 174.0 14.0 10.0
23 seat_stay 1.0 174.0 14.0 10.0
24 chain_stay 1.0 174.0 14.0 10.0
25 paint 3.0 261.0 10.0 12.0
Documentation
Full documentation is available in the docs/ directory:
| File | Description |
|---|---|
docs/cli.md |
Command-line interface reference |
docs/simulation_model.md |
Simulation architecture and event flow |
Minimal Configuration Example
factory_name: "BikeFactory"
months: 12
hours_per_month: 160
show_output: true
product_demand:
"order_01":
MountainBike: 10
bom:
MountainBike:
type: bike
bom:
frame_a: { type: frame, qty: 1 }
wheel_a: { type: wheel, qty: 2 }
pedal: { type: raw, qty: 2 }
frame_a:
type: frame
bom:
tubes: { type: raw, qty: 1 }
seat_stay: { type: raw, qty: 1 }
chain_stay: { type: raw, qty: 1 }
paint: { type: raw, qty: 1.5 }
wheel_a:
type: wheel
bom:
spokes: { type: raw, qty: 15 }
hub: { type: raw, qty: 1 }
rim: { type: raw, qty: 1 }
tire: { type: raw, qty: 1 }
valve: { type: raw, qty: 1 }
reorder_delays:
pedal: { reorder_delay: 10 }
tubes: { reorder_delay: 10 }
seat_stay: { reorder_delay: 10 }
chain_stay: { reorder_delay: 10 }
paint: { reorder_delay: 10 }
spokes: { reorder_delay: 15 }
hub: { reorder_delay: 10 }
rim: { reorder_delay: 10 }
tire: { reorder_delay: 10 }
valve: { reorder_delay: 10 }
initial_inventory:
MountainBike: 0
stock_limits:
MountainBike: { min: 5, max: 20 }
frame_a: { min: 5, max: 15 }
wheel_a: { min: 5, max: 20 }
pedal: { min: 10, max: 30 }
spokes: { min: 30, max: 60 }
hub: { min: 10, max: 20 }
rim: { min: 10, max: 20 }
tire: { min: 10, max: 20 }
valve: { min: 10, max: 20 }
tubes: { min: 10, max: 25 }
seat_stay: { min: 10, max: 25 }
chain_stay: { min: 10, max: 25 }
paint: { min: 10, max: 25 }
machines:
- { name: bk01, type: bike, setup_time: 5, cycle_time: 20 }
- { name: fr01, type: frame, setup_time: 3, cycle_time: 15 }
- { name: wl01, type: wheel, setup_time: 2, cycle_time: 8 }
Project Structure
mla_factory/
├── src/mlafactory
│ ├── Inventory.py # Inventory management and async waiting
│ ├── Machine.py # Machine production process
│ ├── MachineDispatcher.py # Task routing and machine pool management
│ ├── FactorySimulator.py # Core factory coordination
│ ├── FactoryRunner.py # Orchestrator: validation, run, reporting
│ ├── aux_files.py # I/O utilities and custom exceptions
│ ├── aux_intervals.py # Order interval generation
│ ├── aux_reports.py # Result collection and export
│ └── minimal_example/ # Built-in bike factory example
├── docs/
├── tests/
└── README.md
Running Tests
pip install pytest
pytest tests/
License
BSD 3-Clause License. See LICENSE for details.
Citation
To be completed.
Authors
Developer and maintainer:
Oscar J. Castro-Lopez: Research Associate, University of Luxembourg
Contributors:
- Pierrick Pochelu DevOps, LuxProvide
- Georgios Kafanas Infrastructure and Architecture Engineer, University of Luxembourg
Contributions welcome — please open an issue or pull request on GitLab.
Acknowledgements
This project was created with the support of the Luxembourg National Research Fund (FNR) under project 17941664. Supported by the Ministry of Economy (MECO) under project 17941664.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mlafactory-0.1.2.tar.gz.
File metadata
- Download URL: mlafactory-0.1.2.tar.gz
- Upload date:
- Size: 32.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db95da0f0b56f5d8d31476156404290b241dd617ca8fdae96f84bf8ca09d351d
|
|
| MD5 |
714f3ae8c08d8867b93283a7ee0d7e6d
|
|
| BLAKE2b-256 |
a769aca5f80664fc9b7cf7f89262fe0cdc629a0ef91cc4821a935621daa13a98
|
File details
Details for the file mlafactory-0.1.2-py3-none-any.whl.
File metadata
- Download URL: mlafactory-0.1.2-py3-none-any.whl
- Upload date:
- Size: 28.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c85792af1cc7e22dc4f7a25388793c6e3df153e5b2a662fece50571993ff18f6
|
|
| MD5 |
6d95c88358c07b50673509ecea45e3a0
|
|
| BLAKE2b-256 |
18a8126b049f6008e00714d406d768594697969d82b2e93cd26db8aad2d8be7f
|