mlafactory 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mlafactory-0.1.0/LICENSE +11 -0
- mlafactory-0.1.0/MANIFEST.in +1 -0
- mlafactory-0.1.0/PKG-INFO +337 -0
- mlafactory-0.1.0/README.md +312 -0
- mlafactory-0.1.0/pyproject.toml +57 -0
- mlafactory-0.1.0/setup.cfg +4 -0
- mlafactory-0.1.0/src/mlafactory/FactoryRunner.py +411 -0
- mlafactory-0.1.0/src/mlafactory/FactorySimulator.py +349 -0
- mlafactory-0.1.0/src/mlafactory/Inventory.py +96 -0
- mlafactory-0.1.0/src/mlafactory/Machine.py +149 -0
- mlafactory-0.1.0/src/mlafactory/MachineDispatcher.py +182 -0
- mlafactory-0.1.0/src/mlafactory/__init__.py +0 -0
- mlafactory-0.1.0/src/mlafactory/aux_arguments.py +229 -0
- mlafactory-0.1.0/src/mlafactory/aux_files.py +42 -0
- mlafactory-0.1.0/src/mlafactory/aux_intervals.py +75 -0
- mlafactory-0.1.0/src/mlafactory/aux_reports.py +149 -0
- mlafactory-0.1.0/src/mlafactory/minimal_example/__init__.py +0 -0
- mlafactory-0.1.0/src/mlafactory/minimal_example/bom.json +90 -0
- mlafactory-0.1.0/src/mlafactory/minimal_example/initial_inventory.json +31 -0
- mlafactory-0.1.0/src/mlafactory/minimal_example/machines.json +16 -0
- mlafactory-0.1.0/src/mlafactory/minimal_example/orders_demand.json +12 -0
- mlafactory-0.1.0/src/mlafactory/minimal_example/reorder_delays.json +23 -0
- mlafactory-0.1.0/src/mlafactory/minimal_example/stock_limits.json +106 -0
- mlafactory-0.1.0/src/mlafactory/run_factory.py +48 -0
- mlafactory-0.1.0/src/mlafactory.egg-info/PKG-INFO +337 -0
- mlafactory-0.1.0/src/mlafactory.egg-info/SOURCES.txt +30 -0
- mlafactory-0.1.0/src/mlafactory.egg-info/dependency_links.txt +1 -0
- mlafactory-0.1.0/src/mlafactory.egg-info/entry_points.txt +2 -0
- mlafactory-0.1.0/src/mlafactory.egg-info/requires.txt +4 -0
- mlafactory-0.1.0/src/mlafactory.egg-info/top_level.txt +1 -0
- mlafactory-0.1.0/tests/test_mlafactory.py +819 -0
- mlafactory-0.1.0/tests/test_run_factory.py +113 -0
mlafactory-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Copyright 2025 University of Luxembourg
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
|
+
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
+
|
|
7
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
8
|
+
|
|
9
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
10
|
+
|
|
11
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include src/mlafactory/minimal_example *.json
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mlafactory
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Digital Multi-Level Assembly (MLA) manufacturing factory simulation made with SimPy
|
|
5
|
+
Author-email: "Oscar J. Castro-Lopez" <oscar.castro@uni.lu>
|
|
6
|
+
Maintainer-email: Pierrick Pochelu <pierrick.pochelu@gmail.com>, Georgios Kafanas <georgios.kafanas@uni.lu>
|
|
7
|
+
License-Expression: BSD-3-Clause
|
|
8
|
+
Project-URL: Homepage, https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory
|
|
9
|
+
Project-URL: Repository, https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory
|
|
10
|
+
Project-URL: Documentation, https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory
|
|
11
|
+
Keywords: simulation,manufacturing,factory,MLA
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: simpy
|
|
21
|
+
Requires-Dist: pandas
|
|
22
|
+
Requires-Dist: numpy
|
|
23
|
+
Requires-Dist: pyyaml
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# mlafactory
|
|
27
|
+
|
|
28
|
+
[](https://badge.fury.io/py/mlafactory)
|
|
29
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
30
|
+
[](https://www.python.org/downloads/)
|
|
31
|
+
|
|
32
|
+
`mlafactory` is an open-source discrete-event simulation framework for modeling **Multi-Level Assembly (MLA)** manufacturing systems. Built on top of [SimPy](https://simpy.readthedocs.io/), it enables flexible simulation of factories with dynamic inventory management, heterogeneous machine pools, stochastic order arrivals, and configurable production and replenishment policies.
|
|
33
|
+
|
|
34
|
+
The framework is designed for **research, experimentation, and reproducible evaluation** of manufacturing strategies.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **Multi-level bill of materials (BOM)** — recursive assembly of products from sub-components and raw materials
|
|
41
|
+
- **Heterogeneous machine pools** — multiple machine types with configurable setup times, cycle times, and costs
|
|
42
|
+
- **Dynamic inventory management** — min/max stock policies with async waiting and automatic replenishment
|
|
43
|
+
- **Stochastic order arrivals** — fixed, random, spread, or distribution-based inter-order intervals
|
|
44
|
+
- **Configurable replenishment** — per-component reorder delays for raw materials
|
|
45
|
+
- **Multiple inventory initialization strategies** — zero, min, max, or random initial stock levels
|
|
46
|
+
- **Rich reporting** — production service levels, machine utilization, and inventory summaries exported as CSV
|
|
47
|
+
- **CLI and Python API** — run simulations without writing code or integrate programmatically
|
|
48
|
+
- **YAML / JSON configuration** — fully reproducible experiments via configuration files
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Requirements
|
|
53
|
+
|
|
54
|
+
- Python 3.9+
|
|
55
|
+
- SimPy >= 4.0
|
|
56
|
+
- pandas
|
|
57
|
+
- PyYAML
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
<!-- To be completed
|
|
64
|
+
```bash
|
|
65
|
+
pip install mlafactory
|
|
66
|
+
```
|
|
67
|
+
-->
|
|
68
|
+
Install from source:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git clone https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory.git
|
|
72
|
+
cd mla_factory
|
|
73
|
+
pip install -e .
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
### Command Line
|
|
81
|
+
|
|
82
|
+
`mlafactory` ships with a built-in bike factory example:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
mlafactory --show-output
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
To run with a custom configuration file:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
mlafactory --factory-config my_factory.yml --show-output
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Python API
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from mlafactory.FactoryRunner import FactoryRunner
|
|
98
|
+
|
|
99
|
+
# Load from a configuration file
|
|
100
|
+
simulator = FactoryRunner.from_config("my_factory.yml")
|
|
101
|
+
result = simulator.run()
|
|
102
|
+
|
|
103
|
+
# Or configure programmatically
|
|
104
|
+
simulator = FactoryRunner(
|
|
105
|
+
factory_name="BikeFactory",
|
|
106
|
+
bom=bom,
|
|
107
|
+
initial_inventory=initial_inventory,
|
|
108
|
+
reorder_delays=reorder_delays,
|
|
109
|
+
product_demand=product_demand,
|
|
110
|
+
machines=machines,
|
|
111
|
+
stock_limits=stock_limits,
|
|
112
|
+
months=12,
|
|
113
|
+
hours_per_month=160,
|
|
114
|
+
inventory_strategy="max",
|
|
115
|
+
show_output=True,
|
|
116
|
+
export_reports=True,
|
|
117
|
+
output_dir="output/",
|
|
118
|
+
)
|
|
119
|
+
result = simulator.run()
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Expected Output
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Elapsed real time: 0.02940058708190918
|
|
126
|
+
Total simulated time: 1920 hours
|
|
127
|
+
======================================== Production Results ========================================
|
|
128
|
+
product demand fulfilled inventory production fulfillment_ratio production_ratio
|
|
129
|
+
0 RoadBike 52 26 6 32 0.500000 0.615385
|
|
130
|
+
1 MountainBike 65 57 6 63 0.876923 0.969231
|
|
131
|
+
2 ElectricBike 63 28 3 31 0.444444 0.492063
|
|
132
|
+
3 TOTAL 180 111 15 126 0.616667 0.692226
|
|
133
|
+
======================================== Machines Summary ========================================
|
|
134
|
+
type name setup_time cycle_time n_setups n_cycles setup_cost cycle_cost tt_setup tt_build tt_idle
|
|
135
|
+
0 bike bk01 1.0 25.0 13 32 0 0.0 0.216667 13.333333 1906.450000
|
|
136
|
+
1 bike bk02 2.0 20.0 13 32 0 0.0 0.433333 10.666667 1908.900000
|
|
137
|
+
2 bike bk03 3.0 19.0 14 31 0 0.0 0.700000 9.816667 1909.483333
|
|
138
|
+
3 bike bk04 4.0 17.0 14 31 0 0.0 0.933333 8.783333 1910.283333
|
|
139
|
+
4 frame fr01 2.0 15.0 3 43 0 0.0 0.100000 10.750000 1909.150000
|
|
140
|
+
5 frame fr02 3.0 12.0 2 39 0 0.0 0.100000 7.800000 1912.100000
|
|
141
|
+
6 frame fr03 3.0 13.0 3 39 0 0.0 0.150000 8.450000 1911.400000
|
|
142
|
+
7 frame fr04 4.0 14.0 2 53 0 0.0 0.133333 12.366667 1907.500000
|
|
143
|
+
8 wheel wl01 3.0 8.0 29 43 0 0.0 1.450000 5.733333 1912.816667
|
|
144
|
+
9 wheel wl02 10.0 5.0 29 43 0 0.0 4.833333 3.583333 1911.583333
|
|
145
|
+
10 wheel wl03 1.0 10.0 4 42 0 0.0 0.066667 7.000000 1912.933333
|
|
146
|
+
11 wheel wl04 2.0 7.0 4 42 0 0.0 0.133333 4.900000 1914.966667
|
|
147
|
+
12 wheel wl05 9.0 6.0 4 42 0 0.0 0.600000 4.200000 1915.200000
|
|
148
|
+
13 wheel wl06 3.0 5.0 4 42 0 0.0 0.200000 3.500000 1916.300000
|
|
149
|
+
======================================== Inventory Summary ========================================
|
|
150
|
+
item initial consumed final n_reorders
|
|
151
|
+
0 MountainBike 0.0 57.0 6.0 NaN
|
|
152
|
+
1 RoadBike 0.0 26.0 6.0 NaN
|
|
153
|
+
2 ElectricBike 0.0 28.0 3.0 NaN
|
|
154
|
+
3 wheel_a 0.0 126.0 1.0 NaN
|
|
155
|
+
4 wheel_b 0.0 126.0 1.0 NaN
|
|
156
|
+
5 frame_a 0.0 97.0 27.0 NaN
|
|
157
|
+
6 frame_b 0.0 32.0 18.0 NaN
|
|
158
|
+
7 pedal 10.0 258.0 16.0 22.0
|
|
159
|
+
8 crank_arm 5.0 129.0 13.0 22.0
|
|
160
|
+
9 front_derailleur 4.0 129.0 12.0 22.0
|
|
161
|
+
10 chain 3.0 129.0 12.0 22.0
|
|
162
|
+
11 chain_rings 2.0 129.0 12.0 22.0
|
|
163
|
+
12 rear_brakes 1.0 129.0 12.0 22.0
|
|
164
|
+
13 cogset 2.0 129.0 12.0 22.0
|
|
165
|
+
14 rear_derailleur 3.0 129.0 12.0 22.0
|
|
166
|
+
15 spokes 25.0 6350.0 10.0 127.0
|
|
167
|
+
16 hub 1.0 256.0 17.0 24.0
|
|
168
|
+
17 rim 1.0 256.0 17.0 24.0
|
|
169
|
+
18 tire 1.0 256.0 17.0 24.0
|
|
170
|
+
19 valve 1.0 256.0 17.0 24.0
|
|
171
|
+
20 top_tube 1.0 174.0 14.0 10.0
|
|
172
|
+
21 down_tube 1.0 174.0 14.0 10.0
|
|
173
|
+
22 seat_tube 1.0 174.0 14.0 10.0
|
|
174
|
+
23 seat_stay 1.0 174.0 14.0 10.0
|
|
175
|
+
24 chain_stay 1.0 174.0 14.0 10.0
|
|
176
|
+
25 paint 3.0 261.0 10.0 12.0
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Documentation
|
|
182
|
+
|
|
183
|
+
Full documentation is available in the [`docs/`](docs/) directory:
|
|
184
|
+
|
|
185
|
+
| File | Description |
|
|
186
|
+
|---|---|
|
|
187
|
+
| [`docs/cli.md`](docs/cli.md) | Command-line interface reference |
|
|
188
|
+
| [`docs/simulation_model.md`](docs/simulation_model.md) | Simulation architecture and event flow |
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Minimal Configuration Example
|
|
192
|
+
|
|
193
|
+
```yaml
|
|
194
|
+
factory_name: "BikeFactory"
|
|
195
|
+
months: 12
|
|
196
|
+
hours_per_month: 160
|
|
197
|
+
show_output: true
|
|
198
|
+
|
|
199
|
+
product_demand:
|
|
200
|
+
"order_01":
|
|
201
|
+
MountainBike: 10
|
|
202
|
+
|
|
203
|
+
bom:
|
|
204
|
+
MountainBike:
|
|
205
|
+
type: bike
|
|
206
|
+
bom:
|
|
207
|
+
frame_a: { type: frame, qty: 1 }
|
|
208
|
+
wheel_a: { type: wheel, qty: 2 }
|
|
209
|
+
pedal: { type: raw, qty: 2 }
|
|
210
|
+
|
|
211
|
+
frame_a:
|
|
212
|
+
type: frame
|
|
213
|
+
bom:
|
|
214
|
+
tubes: { type: raw, qty: 1 }
|
|
215
|
+
seat_stay: { type: raw, qty: 1 }
|
|
216
|
+
chain_stay: { type: raw, qty: 1 }
|
|
217
|
+
paint: { type: raw, qty: 1.5 }
|
|
218
|
+
|
|
219
|
+
wheel_a:
|
|
220
|
+
type: wheel
|
|
221
|
+
bom:
|
|
222
|
+
spokes: { type: raw, qty: 15 }
|
|
223
|
+
hub: { type: raw, qty: 1 }
|
|
224
|
+
rim: { type: raw, qty: 1 }
|
|
225
|
+
tire: { type: raw, qty: 1 }
|
|
226
|
+
valve: { type: raw, qty: 1 }
|
|
227
|
+
|
|
228
|
+
reorder_delays:
|
|
229
|
+
pedal: { reorder_delay: 10 }
|
|
230
|
+
tubes: { reorder_delay: 10 }
|
|
231
|
+
seat_stay: { reorder_delay: 10 }
|
|
232
|
+
chain_stay: { reorder_delay: 10 }
|
|
233
|
+
paint: { reorder_delay: 10 }
|
|
234
|
+
spokes: { reorder_delay: 15 }
|
|
235
|
+
hub: { reorder_delay: 10 }
|
|
236
|
+
rim: { reorder_delay: 10 }
|
|
237
|
+
tire: { reorder_delay: 10 }
|
|
238
|
+
valve: { reorder_delay: 10 }
|
|
239
|
+
|
|
240
|
+
initial_inventory:
|
|
241
|
+
MountainBike: 0
|
|
242
|
+
|
|
243
|
+
stock_limits:
|
|
244
|
+
MountainBike: { min: 5, max: 20 }
|
|
245
|
+
frame_a: { min: 5, max: 15 }
|
|
246
|
+
wheel_a: { min: 5, max: 20 }
|
|
247
|
+
pedal: { min: 10, max: 30 }
|
|
248
|
+
spokes: { min: 30, max: 60 }
|
|
249
|
+
hub: { min: 10, max: 20 }
|
|
250
|
+
rim: { min: 10, max: 20 }
|
|
251
|
+
tire: { min: 10, max: 20 }
|
|
252
|
+
valve: { min: 10, max: 20 }
|
|
253
|
+
tubes: { min: 10, max: 25 }
|
|
254
|
+
seat_stay: { min: 10, max: 25 }
|
|
255
|
+
chain_stay: { min: 10, max: 25 }
|
|
256
|
+
paint: { min: 10, max: 25 }
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
machines:
|
|
260
|
+
- { name: bk01, type: bike, setup_time: 5, cycle_time: 20 }
|
|
261
|
+
- { name: fr01, type: frame, setup_time: 3, cycle_time: 15 }
|
|
262
|
+
- { name: wl01, type: wheel, setup_time: 2, cycle_time: 8 }
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Project Structure
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
mla_factory/
|
|
271
|
+
├── src/mlafactory
|
|
272
|
+
│ ├── Inventory.py # Inventory management and async waiting
|
|
273
|
+
│ ├── Machine.py # Machine production process
|
|
274
|
+
│ ├── MachineDispatcher.py # Task routing and machine pool management
|
|
275
|
+
│ ├── FactorySimulator.py # Core factory coordination
|
|
276
|
+
│ ├── FactoryRunner.py # Orchestrator: validation, run, reporting
|
|
277
|
+
│ ├── aux_files.py # I/O utilities and custom exceptions
|
|
278
|
+
│ ├── aux_intervals.py # Order interval generation
|
|
279
|
+
│ ├── aux_reports.py # Result collection and export
|
|
280
|
+
│ └── minimal_example/ # Built-in bike factory example
|
|
281
|
+
├── docs/
|
|
282
|
+
├── tests/
|
|
283
|
+
└── README.md
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Running Tests
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
pip install pytest
|
|
292
|
+
pytest tests/
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
BSD 3-Clause License. See [LICENSE](LICENSE) for details.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Citation
|
|
304
|
+
|
|
305
|
+
To be completed.
|
|
306
|
+
<!--
|
|
307
|
+
If you use mlafactory in your research, please cite:
|
|
308
|
+
|
|
309
|
+
```bibtex
|
|
310
|
+
@article{mlafactory2025,
|
|
311
|
+
title = {mlafactory: A Discrete-Event Simulation Framework for Multi-Level Assembly Systems},
|
|
312
|
+
author = {Your Name},
|
|
313
|
+
journal = {Journal of Open Source Software},
|
|
314
|
+
year = {2025},
|
|
315
|
+
doi = {10.xxxx/joss.xxxxx}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
-->
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Authors
|
|
322
|
+
|
|
323
|
+
Developer and maintainer:
|
|
324
|
+
|
|
325
|
+
**Oscar J. Castro-Lopez**:
|
|
326
|
+
Research Associate, University of Luxembourg
|
|
327
|
+
|
|
328
|
+
Contributors:
|
|
329
|
+
|
|
330
|
+
- **Pierrick Pochelu** DevOps, LuxProvide
|
|
331
|
+
- **Georgios Kafanas** Infrastructure and Architecture Engineer, University of Luxembourg
|
|
332
|
+
|
|
333
|
+
Contributions welcome — please open an issue or pull request on GitLab.
|
|
334
|
+
|
|
335
|
+
## Acknowledgements
|
|
336
|
+
|
|
337
|
+
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.
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# mlafactory
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/py/mlafactory)
|
|
4
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
|
|
7
|
+
`mlafactory` is an open-source discrete-event simulation framework for modeling **Multi-Level Assembly (MLA)** manufacturing systems. Built on top of [SimPy](https://simpy.readthedocs.io/), it enables flexible simulation of factories with dynamic inventory management, heterogeneous machine pools, stochastic order arrivals, and configurable production and replenishment policies.
|
|
8
|
+
|
|
9
|
+
The framework is designed for **research, experimentation, and reproducible evaluation** of manufacturing strategies.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Multi-level bill of materials (BOM)** — recursive assembly of products from sub-components and raw materials
|
|
16
|
+
- **Heterogeneous machine pools** — multiple machine types with configurable setup times, cycle times, and costs
|
|
17
|
+
- **Dynamic inventory management** — min/max stock policies with async waiting and automatic replenishment
|
|
18
|
+
- **Stochastic order arrivals** — fixed, random, spread, or distribution-based inter-order intervals
|
|
19
|
+
- **Configurable replenishment** — per-component reorder delays for raw materials
|
|
20
|
+
- **Multiple inventory initialization strategies** — zero, min, max, or random initial stock levels
|
|
21
|
+
- **Rich reporting** — production service levels, machine utilization, and inventory summaries exported as CSV
|
|
22
|
+
- **CLI and Python API** — run simulations without writing code or integrate programmatically
|
|
23
|
+
- **YAML / JSON configuration** — fully reproducible experiments via configuration files
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Requirements
|
|
28
|
+
|
|
29
|
+
- Python 3.9+
|
|
30
|
+
- SimPy >= 4.0
|
|
31
|
+
- pandas
|
|
32
|
+
- PyYAML
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
<!-- To be completed
|
|
39
|
+
```bash
|
|
40
|
+
pip install mlafactory
|
|
41
|
+
```
|
|
42
|
+
-->
|
|
43
|
+
Install from source:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory.git
|
|
47
|
+
cd mla_factory
|
|
48
|
+
pip install -e .
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
### Command Line
|
|
56
|
+
|
|
57
|
+
`mlafactory` ships with a built-in bike factory example:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
mlafactory --show-output
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
To run with a custom configuration file:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
mlafactory --factory-config my_factory.yml --show-output
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Python API
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from mlafactory.FactoryRunner import FactoryRunner
|
|
73
|
+
|
|
74
|
+
# Load from a configuration file
|
|
75
|
+
simulator = FactoryRunner.from_config("my_factory.yml")
|
|
76
|
+
result = simulator.run()
|
|
77
|
+
|
|
78
|
+
# Or configure programmatically
|
|
79
|
+
simulator = FactoryRunner(
|
|
80
|
+
factory_name="BikeFactory",
|
|
81
|
+
bom=bom,
|
|
82
|
+
initial_inventory=initial_inventory,
|
|
83
|
+
reorder_delays=reorder_delays,
|
|
84
|
+
product_demand=product_demand,
|
|
85
|
+
machines=machines,
|
|
86
|
+
stock_limits=stock_limits,
|
|
87
|
+
months=12,
|
|
88
|
+
hours_per_month=160,
|
|
89
|
+
inventory_strategy="max",
|
|
90
|
+
show_output=True,
|
|
91
|
+
export_reports=True,
|
|
92
|
+
output_dir="output/",
|
|
93
|
+
)
|
|
94
|
+
result = simulator.run()
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Expected Output
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Elapsed real time: 0.02940058708190918
|
|
101
|
+
Total simulated time: 1920 hours
|
|
102
|
+
======================================== Production Results ========================================
|
|
103
|
+
product demand fulfilled inventory production fulfillment_ratio production_ratio
|
|
104
|
+
0 RoadBike 52 26 6 32 0.500000 0.615385
|
|
105
|
+
1 MountainBike 65 57 6 63 0.876923 0.969231
|
|
106
|
+
2 ElectricBike 63 28 3 31 0.444444 0.492063
|
|
107
|
+
3 TOTAL 180 111 15 126 0.616667 0.692226
|
|
108
|
+
======================================== Machines Summary ========================================
|
|
109
|
+
type name setup_time cycle_time n_setups n_cycles setup_cost cycle_cost tt_setup tt_build tt_idle
|
|
110
|
+
0 bike bk01 1.0 25.0 13 32 0 0.0 0.216667 13.333333 1906.450000
|
|
111
|
+
1 bike bk02 2.0 20.0 13 32 0 0.0 0.433333 10.666667 1908.900000
|
|
112
|
+
2 bike bk03 3.0 19.0 14 31 0 0.0 0.700000 9.816667 1909.483333
|
|
113
|
+
3 bike bk04 4.0 17.0 14 31 0 0.0 0.933333 8.783333 1910.283333
|
|
114
|
+
4 frame fr01 2.0 15.0 3 43 0 0.0 0.100000 10.750000 1909.150000
|
|
115
|
+
5 frame fr02 3.0 12.0 2 39 0 0.0 0.100000 7.800000 1912.100000
|
|
116
|
+
6 frame fr03 3.0 13.0 3 39 0 0.0 0.150000 8.450000 1911.400000
|
|
117
|
+
7 frame fr04 4.0 14.0 2 53 0 0.0 0.133333 12.366667 1907.500000
|
|
118
|
+
8 wheel wl01 3.0 8.0 29 43 0 0.0 1.450000 5.733333 1912.816667
|
|
119
|
+
9 wheel wl02 10.0 5.0 29 43 0 0.0 4.833333 3.583333 1911.583333
|
|
120
|
+
10 wheel wl03 1.0 10.0 4 42 0 0.0 0.066667 7.000000 1912.933333
|
|
121
|
+
11 wheel wl04 2.0 7.0 4 42 0 0.0 0.133333 4.900000 1914.966667
|
|
122
|
+
12 wheel wl05 9.0 6.0 4 42 0 0.0 0.600000 4.200000 1915.200000
|
|
123
|
+
13 wheel wl06 3.0 5.0 4 42 0 0.0 0.200000 3.500000 1916.300000
|
|
124
|
+
======================================== Inventory Summary ========================================
|
|
125
|
+
item initial consumed final n_reorders
|
|
126
|
+
0 MountainBike 0.0 57.0 6.0 NaN
|
|
127
|
+
1 RoadBike 0.0 26.0 6.0 NaN
|
|
128
|
+
2 ElectricBike 0.0 28.0 3.0 NaN
|
|
129
|
+
3 wheel_a 0.0 126.0 1.0 NaN
|
|
130
|
+
4 wheel_b 0.0 126.0 1.0 NaN
|
|
131
|
+
5 frame_a 0.0 97.0 27.0 NaN
|
|
132
|
+
6 frame_b 0.0 32.0 18.0 NaN
|
|
133
|
+
7 pedal 10.0 258.0 16.0 22.0
|
|
134
|
+
8 crank_arm 5.0 129.0 13.0 22.0
|
|
135
|
+
9 front_derailleur 4.0 129.0 12.0 22.0
|
|
136
|
+
10 chain 3.0 129.0 12.0 22.0
|
|
137
|
+
11 chain_rings 2.0 129.0 12.0 22.0
|
|
138
|
+
12 rear_brakes 1.0 129.0 12.0 22.0
|
|
139
|
+
13 cogset 2.0 129.0 12.0 22.0
|
|
140
|
+
14 rear_derailleur 3.0 129.0 12.0 22.0
|
|
141
|
+
15 spokes 25.0 6350.0 10.0 127.0
|
|
142
|
+
16 hub 1.0 256.0 17.0 24.0
|
|
143
|
+
17 rim 1.0 256.0 17.0 24.0
|
|
144
|
+
18 tire 1.0 256.0 17.0 24.0
|
|
145
|
+
19 valve 1.0 256.0 17.0 24.0
|
|
146
|
+
20 top_tube 1.0 174.0 14.0 10.0
|
|
147
|
+
21 down_tube 1.0 174.0 14.0 10.0
|
|
148
|
+
22 seat_tube 1.0 174.0 14.0 10.0
|
|
149
|
+
23 seat_stay 1.0 174.0 14.0 10.0
|
|
150
|
+
24 chain_stay 1.0 174.0 14.0 10.0
|
|
151
|
+
25 paint 3.0 261.0 10.0 12.0
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Documentation
|
|
157
|
+
|
|
158
|
+
Full documentation is available in the [`docs/`](docs/) directory:
|
|
159
|
+
|
|
160
|
+
| File | Description |
|
|
161
|
+
|---|---|
|
|
162
|
+
| [`docs/cli.md`](docs/cli.md) | Command-line interface reference |
|
|
163
|
+
| [`docs/simulation_model.md`](docs/simulation_model.md) | Simulation architecture and event flow |
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Minimal Configuration Example
|
|
167
|
+
|
|
168
|
+
```yaml
|
|
169
|
+
factory_name: "BikeFactory"
|
|
170
|
+
months: 12
|
|
171
|
+
hours_per_month: 160
|
|
172
|
+
show_output: true
|
|
173
|
+
|
|
174
|
+
product_demand:
|
|
175
|
+
"order_01":
|
|
176
|
+
MountainBike: 10
|
|
177
|
+
|
|
178
|
+
bom:
|
|
179
|
+
MountainBike:
|
|
180
|
+
type: bike
|
|
181
|
+
bom:
|
|
182
|
+
frame_a: { type: frame, qty: 1 }
|
|
183
|
+
wheel_a: { type: wheel, qty: 2 }
|
|
184
|
+
pedal: { type: raw, qty: 2 }
|
|
185
|
+
|
|
186
|
+
frame_a:
|
|
187
|
+
type: frame
|
|
188
|
+
bom:
|
|
189
|
+
tubes: { type: raw, qty: 1 }
|
|
190
|
+
seat_stay: { type: raw, qty: 1 }
|
|
191
|
+
chain_stay: { type: raw, qty: 1 }
|
|
192
|
+
paint: { type: raw, qty: 1.5 }
|
|
193
|
+
|
|
194
|
+
wheel_a:
|
|
195
|
+
type: wheel
|
|
196
|
+
bom:
|
|
197
|
+
spokes: { type: raw, qty: 15 }
|
|
198
|
+
hub: { type: raw, qty: 1 }
|
|
199
|
+
rim: { type: raw, qty: 1 }
|
|
200
|
+
tire: { type: raw, qty: 1 }
|
|
201
|
+
valve: { type: raw, qty: 1 }
|
|
202
|
+
|
|
203
|
+
reorder_delays:
|
|
204
|
+
pedal: { reorder_delay: 10 }
|
|
205
|
+
tubes: { reorder_delay: 10 }
|
|
206
|
+
seat_stay: { reorder_delay: 10 }
|
|
207
|
+
chain_stay: { reorder_delay: 10 }
|
|
208
|
+
paint: { reorder_delay: 10 }
|
|
209
|
+
spokes: { reorder_delay: 15 }
|
|
210
|
+
hub: { reorder_delay: 10 }
|
|
211
|
+
rim: { reorder_delay: 10 }
|
|
212
|
+
tire: { reorder_delay: 10 }
|
|
213
|
+
valve: { reorder_delay: 10 }
|
|
214
|
+
|
|
215
|
+
initial_inventory:
|
|
216
|
+
MountainBike: 0
|
|
217
|
+
|
|
218
|
+
stock_limits:
|
|
219
|
+
MountainBike: { min: 5, max: 20 }
|
|
220
|
+
frame_a: { min: 5, max: 15 }
|
|
221
|
+
wheel_a: { min: 5, max: 20 }
|
|
222
|
+
pedal: { min: 10, max: 30 }
|
|
223
|
+
spokes: { min: 30, max: 60 }
|
|
224
|
+
hub: { min: 10, max: 20 }
|
|
225
|
+
rim: { min: 10, max: 20 }
|
|
226
|
+
tire: { min: 10, max: 20 }
|
|
227
|
+
valve: { min: 10, max: 20 }
|
|
228
|
+
tubes: { min: 10, max: 25 }
|
|
229
|
+
seat_stay: { min: 10, max: 25 }
|
|
230
|
+
chain_stay: { min: 10, max: 25 }
|
|
231
|
+
paint: { min: 10, max: 25 }
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
machines:
|
|
235
|
+
- { name: bk01, type: bike, setup_time: 5, cycle_time: 20 }
|
|
236
|
+
- { name: fr01, type: frame, setup_time: 3, cycle_time: 15 }
|
|
237
|
+
- { name: wl01, type: wheel, setup_time: 2, cycle_time: 8 }
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Project Structure
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
mla_factory/
|
|
246
|
+
├── src/mlafactory
|
|
247
|
+
│ ├── Inventory.py # Inventory management and async waiting
|
|
248
|
+
│ ├── Machine.py # Machine production process
|
|
249
|
+
│ ├── MachineDispatcher.py # Task routing and machine pool management
|
|
250
|
+
│ ├── FactorySimulator.py # Core factory coordination
|
|
251
|
+
│ ├── FactoryRunner.py # Orchestrator: validation, run, reporting
|
|
252
|
+
│ ├── aux_files.py # I/O utilities and custom exceptions
|
|
253
|
+
│ ├── aux_intervals.py # Order interval generation
|
|
254
|
+
│ ├── aux_reports.py # Result collection and export
|
|
255
|
+
│ └── minimal_example/ # Built-in bike factory example
|
|
256
|
+
├── docs/
|
|
257
|
+
├── tests/
|
|
258
|
+
└── README.md
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Running Tests
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
pip install pytest
|
|
267
|
+
pytest tests/
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## License
|
|
273
|
+
|
|
274
|
+
BSD 3-Clause License. See [LICENSE](LICENSE) for details.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Citation
|
|
279
|
+
|
|
280
|
+
To be completed.
|
|
281
|
+
<!--
|
|
282
|
+
If you use mlafactory in your research, please cite:
|
|
283
|
+
|
|
284
|
+
```bibtex
|
|
285
|
+
@article{mlafactory2025,
|
|
286
|
+
title = {mlafactory: A Discrete-Event Simulation Framework for Multi-Level Assembly Systems},
|
|
287
|
+
author = {Your Name},
|
|
288
|
+
journal = {Journal of Open Source Software},
|
|
289
|
+
year = {2025},
|
|
290
|
+
doi = {10.xxxx/joss.xxxxx}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
-->
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Authors
|
|
297
|
+
|
|
298
|
+
Developer and maintainer:
|
|
299
|
+
|
|
300
|
+
**Oscar J. Castro-Lopez**:
|
|
301
|
+
Research Associate, University of Luxembourg
|
|
302
|
+
|
|
303
|
+
Contributors:
|
|
304
|
+
|
|
305
|
+
- **Pierrick Pochelu** DevOps, LuxProvide
|
|
306
|
+
- **Georgios Kafanas** Infrastructure and Architecture Engineer, University of Luxembourg
|
|
307
|
+
|
|
308
|
+
Contributions welcome — please open an issue or pull request on GitLab.
|
|
309
|
+
|
|
310
|
+
## Acknowledgements
|
|
311
|
+
|
|
312
|
+
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.
|