Skip to main content

Digital Multi-Level Assembly (MLA) manufacturing factory simulation made with SimPy

Project description

mlafactory

PyPI version License: BSD-3 Python 3.9+

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

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mlafactory-0.1.1.tar.gz (32.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mlafactory-0.1.1-py3-none-any.whl (28.0 kB view details)

Uploaded Python 3

File details

Details for the file mlafactory-0.1.1.tar.gz.

File metadata

  • Download URL: mlafactory-0.1.1.tar.gz
  • Upload date:
  • Size: 32.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for mlafactory-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b71966a7bc345204a54cdd0223eac0d70c936cfe71caa3a057d4ddba22b8e421
MD5 aeb5030cfdfb1ee2f8094c810af628bf
BLAKE2b-256 24061ead467004c3752cc7a8b47c5044d09e7e898af4598fccd31cb9b58d796b

See more details on using hashes here.

File details

Details for the file mlafactory-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: mlafactory-0.1.1-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

Hashes for mlafactory-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ebb2ac1236e847faad74b06c7f912960d327474df03312f935db9c8c69cfaf22
MD5 281b6e683ba3e6abcb717fc04352fc51
BLAKE2b-256 26388403b291f2993da75b6e0092f1d2fbda992cbdbf1c23d9d780c5a3b32ab1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page