mlafactory 0.1.2__tar.gz → 0.2.3__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.2 → mlafactory-0.2.3}/MANIFEST.in +1 -0
- mlafactory-0.2.3/PKG-INFO +247 -0
- mlafactory-0.2.3/README.md +212 -0
- mlafactory-0.2.3/pyproject.toml +86 -0
- mlafactory-0.2.3/src/mlafactory/__init__.py +5 -0
- mlafactory-0.2.3/src/mlafactory/cli.py +108 -0
- mlafactory-0.2.3/src/mlafactory/config/arguments.py +288 -0
- mlafactory-0.2.3/src/mlafactory/config/bom.py +41 -0
- mlafactory-0.2.3/src/mlafactory/config/config.py +181 -0
- mlafactory-0.2.3/src/mlafactory/config/files.py +39 -0
- mlafactory-0.2.3/src/mlafactory/config/intervals.py +78 -0
- mlafactory-0.2.3/src/mlafactory/config/objectives.py +77 -0
- mlafactory-0.1.2/src/mlafactory/aux_reports.py → mlafactory-0.2.3/src/mlafactory/config/reports.py +66 -51
- mlafactory-0.2.3/src/mlafactory/config/result.py +228 -0
- mlafactory-0.2.3/src/mlafactory/config/validation.py +155 -0
- {mlafactory-0.1.2/src/mlafactory/minimal_example → mlafactory-0.2.3/src/mlafactory/examples/individual_files}/bom.json +34 -26
- mlafactory-0.1.2/src/mlafactory/minimal_example/stock_limits.json → mlafactory-0.2.3/src/mlafactory/examples/individual_files/inventory_policy_bounds.json +38 -26
- mlafactory-0.2.3/src/mlafactory/examples/individual_files/machines.json +5 -0
- mlafactory-0.2.3/src/mlafactory/examples/individual_files/orders.json +14 -0
- mlafactory-0.1.2/src/mlafactory/minimal_example/reorder_delays.json → mlafactory-0.2.3/src/mlafactory/examples/individual_files/supplier_lead_times.json +5 -1
- mlafactory-0.2.3/src/mlafactory/examples/min_example.json +287 -0
- mlafactory-0.2.3/src/mlafactory/examples/min_example.yaml +112 -0
- mlafactory-0.2.3/src/mlafactory/optimization/optimize_stock_policy.py +54 -0
- mlafactory-0.2.3/src/mlafactory/optimization/stock_policy_problem.py +209 -0
- mlafactory-0.2.3/src/mlafactory/runner.py +233 -0
- mlafactory-0.2.3/src/mlafactory/scenario/initial_inventory.py +59 -0
- mlafactory-0.2.3/src/mlafactory/scenario/orders.py +65 -0
- mlafactory-0.2.3/src/mlafactory/sim/__init__.py +0 -0
- mlafactory-0.1.2/src/mlafactory/MachineDispatcher.py → mlafactory-0.2.3/src/mlafactory/sim/dispatcher.py +15 -13
- mlafactory-0.1.2/src/mlafactory/Machine.py → mlafactory-0.2.3/src/mlafactory/sim/machine.py +13 -2
- mlafactory-0.1.2/src/mlafactory/FactorySimulator.py → mlafactory-0.2.3/src/mlafactory/sim/simulator.py +91 -69
- mlafactory-0.1.2/src/mlafactory/Inventory.py → mlafactory-0.2.3/src/mlafactory/sim/stock.py +13 -9
- mlafactory-0.2.3/src/mlafactory.egg-info/PKG-INFO +247 -0
- mlafactory-0.2.3/src/mlafactory.egg-info/SOURCES.txt +52 -0
- mlafactory-0.2.3/src/mlafactory.egg-info/entry_points.txt +2 -0
- mlafactory-0.2.3/src/mlafactory.egg-info/requires.txt +12 -0
- mlafactory-0.2.3/tests/test_arguments.py +159 -0
- mlafactory-0.2.3/tests/test_bike_integration.py +114 -0
- mlafactory-0.2.3/tests/test_cli.py +195 -0
- mlafactory-0.2.3/tests/test_config.py +246 -0
- mlafactory-0.2.3/tests/test_des_scenarios.py +94 -0
- mlafactory-0.2.3/tests/test_intervals_objectives.py +127 -0
- mlafactory-0.2.3/tests/test_result.py +195 -0
- mlafactory-0.2.3/tests/test_runner_run.py +152 -0
- mlafactory-0.2.3/tests/test_stock_policy_problem.py +29 -0
- mlafactory-0.2.3/tests/test_validation.py +161 -0
- mlafactory-0.1.2/PKG-INFO +0 -336
- mlafactory-0.1.2/README.md +0 -312
- mlafactory-0.1.2/pyproject.toml +0 -53
- mlafactory-0.1.2/src/mlafactory/FactoryRunner.py +0 -411
- mlafactory-0.1.2/src/mlafactory/aux_arguments.py +0 -229
- mlafactory-0.1.2/src/mlafactory/aux_files.py +0 -42
- mlafactory-0.1.2/src/mlafactory/aux_intervals.py +0 -75
- mlafactory-0.1.2/src/mlafactory/minimal_example/orders_demand.json +0 -12
- mlafactory-0.1.2/src/mlafactory/run_factory.py +0 -48
- mlafactory-0.1.2/src/mlafactory.egg-info/PKG-INFO +0 -336
- mlafactory-0.1.2/src/mlafactory.egg-info/SOURCES.txt +0 -30
- mlafactory-0.1.2/src/mlafactory.egg-info/entry_points.txt +0 -2
- mlafactory-0.1.2/src/mlafactory.egg-info/requires.txt +0 -4
- mlafactory-0.1.2/tests/test_mlafactory.py +0 -819
- mlafactory-0.1.2/tests/test_run_factory.py +0 -113
- {mlafactory-0.1.2 → mlafactory-0.2.3}/LICENSE +0 -0
- {mlafactory-0.1.2 → mlafactory-0.2.3}/setup.cfg +0 -0
- {mlafactory-0.1.2/src/mlafactory → mlafactory-0.2.3/src/mlafactory/config}/__init__.py +0 -0
- {mlafactory-0.1.2/src/mlafactory/minimal_example → mlafactory-0.2.3/src/mlafactory/examples/individual_files}/initial_inventory.json +0 -0
- /mlafactory-0.1.2/src/mlafactory/minimal_example/machines.json → /mlafactory-0.2.3/src/mlafactory/examples/individual_files/machines copy.json +0 -0
- {mlafactory-0.1.2/src/mlafactory/minimal_example → mlafactory-0.2.3/src/mlafactory/scenario}/__init__.py +0 -0
- {mlafactory-0.1.2 → mlafactory-0.2.3}/src/mlafactory.egg-info/dependency_links.txt +0 -0
- {mlafactory-0.1.2 → mlafactory-0.2.3}/src/mlafactory.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mlafactory
|
|
3
|
+
Version: 0.2.3
|
|
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
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory
|
|
8
|
+
Project-URL: Repository, https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory
|
|
9
|
+
Project-URL: Documentation, https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory
|
|
10
|
+
Project-URL: Issues, https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory/-/issues
|
|
11
|
+
Keywords: simulation,manufacturing,factory,MLA,discrete-event simulation,simpy
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Intended Audience :: Science/Research
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: simpy>=4.0
|
|
25
|
+
Requires-Dist: numpy>=1.23.2
|
|
26
|
+
Requires-Dist: pandas>=1.5
|
|
27
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
28
|
+
Provides-Extra: test
|
|
29
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
30
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: mlafactory[test]; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff==0.15.6; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# mlafactory
|
|
37
|
+
|
|
38
|
+
[](https://badge.fury.io/py/mlafactory)
|
|
39
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
40
|
+
[](https://www.python.org/downloads/)
|
|
41
|
+
|
|
42
|
+
`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.
|
|
43
|
+
|
|
44
|
+
The framework is designed for **research, experimentation, and reproducible evaluation** of manufacturing strategies.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **Multi-level bill of materials (BOM)** — recursive assembly of products from sub-components and raw materials
|
|
51
|
+
- **Heterogeneous machine pools** — multiple machine types with configurable setup times, cycle times, and costs
|
|
52
|
+
- **Dynamic inventory management** — min/max stock policies with async waiting and automatic replenishment
|
|
53
|
+
- **Stochastic order arrivals** — fixed, random, spread, or distribution-based inter-order intervals
|
|
54
|
+
- **Configurable replenishment** — per-component reorder delays for raw materials
|
|
55
|
+
- **Multiple inventory initialization strategies** — zero, min, max, or random initial stock levels
|
|
56
|
+
- **Rich reporting** — production service levels, machine utilization, and inventory summaries exported as CSV
|
|
57
|
+
- **CLI and Python API** — run simulations without writing code or integrate programmatically
|
|
58
|
+
- **YAML / JSON configuration** — fully reproducible experiments via configuration files
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Requirements
|
|
63
|
+
|
|
64
|
+
- Python 3.11+
|
|
65
|
+
- SimPy >= 4.0
|
|
66
|
+
- NumPy
|
|
67
|
+
- pandas
|
|
68
|
+
- PyYAML
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install mlafactory
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Install from source:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory.git
|
|
83
|
+
cd mla_factory
|
|
84
|
+
pip install -e .
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Quick Start
|
|
90
|
+
|
|
91
|
+
### Command Line
|
|
92
|
+
|
|
93
|
+
The CLI uses the bundled example configuration when no input options are
|
|
94
|
+
provided. Print a summary with:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
mlafactory --print-summary
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Run a custom YAML or JSON configuration:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
mlafactory --factory-config my_factory.yml --print-summary
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Python API
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from mlafactory import FactoryRunner
|
|
110
|
+
|
|
111
|
+
runner = FactoryRunner.from_config("my_factory.yml")
|
|
112
|
+
result = runner.run()
|
|
113
|
+
|
|
114
|
+
print(result.fulfillment_ratio)
|
|
115
|
+
print(result.production) # pandas DataFrame, including a TOTAL row
|
|
116
|
+
|
|
117
|
+
# Score a run directly. "production" aliases total "produced_qty".
|
|
118
|
+
score = runner.run_objective("fulfillment_ratio")
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
To configure a runner in Python, create a `FactoryConfig` and `RunOptions`:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from mlafactory.config.config import FactoryConfig, RunOptions
|
|
125
|
+
from mlafactory import FactoryRunner
|
|
126
|
+
|
|
127
|
+
# config_data is a mapping with the fields in the sample YAML/JSON file.
|
|
128
|
+
# congid_data must contain 'orders', 'bom', 'initial_inventory', 'machines', 'inventory_policy_bounds', and 'supplier_lead_times'
|
|
129
|
+
config = FactoryConfig.from_dict(config_data)
|
|
130
|
+
options = RunOptions(print_summary=True)
|
|
131
|
+
runner = FactoryRunner(config, options)
|
|
132
|
+
result = runner.run()
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The full sample configurations are [`min_example.yaml`](src/mlafactory/examples/min_example.yaml) and [`min_example.json`](src/mlafactory/examples/min_example.json).
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Documentation
|
|
140
|
+
|
|
141
|
+
Additional documentation is available in [`docs/`](docs/):
|
|
142
|
+
|
|
143
|
+
| File | Description |
|
|
144
|
+
|---|---|
|
|
145
|
+
| [`docs/cli.md`](docs/cli.md) | Additional command-line usage notes |
|
|
146
|
+
| [`docs/simulation_model.md`](docs/simulation_model.md) | Simulation architecture and event flow |
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Configuration
|
|
150
|
+
|
|
151
|
+
Use one YAML or JSON configuration file with these top-level sections:
|
|
152
|
+
|
|
153
|
+
- `orders`: mapping of order IDs to product quantities
|
|
154
|
+
- `bom`: products and components, each with a machine `type` and nested `bom`
|
|
155
|
+
- `machines`: machine names, types, setup/cycle times, and optional costs
|
|
156
|
+
- `supplier_lead_times`: raw material reorder delays
|
|
157
|
+
- `inventory_policy_bounds`: `min` and `max` stock limits for every BOM or
|
|
158
|
+
supplier item
|
|
159
|
+
- `initial_inventory`: optional explicit starting stock
|
|
160
|
+
- Optional run settings include `factory_name`, `months`, `hours_per_month`,
|
|
161
|
+
`seed`, `inventory_strategy`, `order_mode`, and `order_mode_params`
|
|
162
|
+
|
|
163
|
+
For complete, valid examples, see [`min_example.yaml`](src/mlafactory/examples/min_example.yaml)
|
|
164
|
+
or [`min_example.json`](src/mlafactory/examples/min_example.json). Machine setup
|
|
165
|
+
and cycle times are expressed in minutes; the simulation duration and reorder
|
|
166
|
+
delays use simulation-time hours.
|
|
167
|
+
|
|
168
|
+
Order interval modes are `fixed`, `random`, `spread`, and `distribution`.
|
|
169
|
+
Distribution mode supports `poisson` and `normal`. The configured seed controls
|
|
170
|
+
random initial inventory and stochastic order intervals.
|
|
171
|
+
|
|
172
|
+
To export CSV reports, set `export_reports: true` in the configuration or pass
|
|
173
|
+
`--export-reports`; choose the destination with `output_dir` or `--output-dir`.
|
|
174
|
+
The CLI options `--print-summary`, `--debug-logs`, and `--export-reports` enable
|
|
175
|
+
their respective outputs.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Project Structure
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
mlafactory/
|
|
183
|
+
├── src/mlafactory/
|
|
184
|
+
│ ├── cli.py # command-line entry point
|
|
185
|
+
│ ├── runner.py # public simulation orchestrator
|
|
186
|
+
│ ├── config/ # configuration, validation, and reporting
|
|
187
|
+
│ ├── examples/ # bundled YAML/JSON configurations
|
|
188
|
+
│ ├── optimization/ # stock-policy optimization adapter
|
|
189
|
+
│ ├── scenario/ # initial inventory and order scheduling
|
|
190
|
+
│ └── sim/ # SimPy simulation entities
|
|
191
|
+
├── docs/
|
|
192
|
+
├── tests/
|
|
193
|
+
└── README.md
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Running Tests
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
pip install -e ".[test]"
|
|
202
|
+
python -m pytest
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
BSD 3-Clause License. See [LICENSE](LICENSE) for details.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Citation
|
|
214
|
+
|
|
215
|
+
To be completed.
|
|
216
|
+
<!--
|
|
217
|
+
If you use mlafactory in your research, please cite:
|
|
218
|
+
|
|
219
|
+
```bibtex
|
|
220
|
+
@article{mlafactory2025,
|
|
221
|
+
title = {mlafactory: A Discrete-Event Simulation Framework for Multi-Level Assembly Systems},
|
|
222
|
+
author = {Your Name},
|
|
223
|
+
journal = {Journal of Open Source Software},
|
|
224
|
+
year = {2025},
|
|
225
|
+
doi = {10.xxxx/joss.xxxxx}
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
-->
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Authors
|
|
232
|
+
|
|
233
|
+
Developer and maintainer:
|
|
234
|
+
|
|
235
|
+
**Oscar J. Castro-Lopez**:
|
|
236
|
+
Research Associate, University of Luxembourg
|
|
237
|
+
|
|
238
|
+
Contributors:
|
|
239
|
+
|
|
240
|
+
- **Pierrick Pochelu** DevOps, LuxProvide
|
|
241
|
+
- **Georgios Kafanas** Infrastructure and Architecture Engineer, University of Luxembourg
|
|
242
|
+
|
|
243
|
+
Contributions welcome — please open an issue or pull request on GitLab.
|
|
244
|
+
|
|
245
|
+
## Acknowledgements
|
|
246
|
+
|
|
247
|
+
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,212 @@
|
|
|
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.11+
|
|
30
|
+
- SimPy >= 4.0
|
|
31
|
+
- NumPy
|
|
32
|
+
- pandas
|
|
33
|
+
- PyYAML
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install mlafactory
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Install from source:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git clone https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory.git
|
|
48
|
+
cd mla_factory
|
|
49
|
+
pip install -e .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
### Command Line
|
|
57
|
+
|
|
58
|
+
The CLI uses the bundled example configuration when no input options are
|
|
59
|
+
provided. Print a summary with:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
mlafactory --print-summary
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Run a custom YAML or JSON configuration:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
mlafactory --factory-config my_factory.yml --print-summary
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Python API
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from mlafactory import FactoryRunner
|
|
75
|
+
|
|
76
|
+
runner = FactoryRunner.from_config("my_factory.yml")
|
|
77
|
+
result = runner.run()
|
|
78
|
+
|
|
79
|
+
print(result.fulfillment_ratio)
|
|
80
|
+
print(result.production) # pandas DataFrame, including a TOTAL row
|
|
81
|
+
|
|
82
|
+
# Score a run directly. "production" aliases total "produced_qty".
|
|
83
|
+
score = runner.run_objective("fulfillment_ratio")
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
To configure a runner in Python, create a `FactoryConfig` and `RunOptions`:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from mlafactory.config.config import FactoryConfig, RunOptions
|
|
90
|
+
from mlafactory import FactoryRunner
|
|
91
|
+
|
|
92
|
+
# config_data is a mapping with the fields in the sample YAML/JSON file.
|
|
93
|
+
# congid_data must contain 'orders', 'bom', 'initial_inventory', 'machines', 'inventory_policy_bounds', and 'supplier_lead_times'
|
|
94
|
+
config = FactoryConfig.from_dict(config_data)
|
|
95
|
+
options = RunOptions(print_summary=True)
|
|
96
|
+
runner = FactoryRunner(config, options)
|
|
97
|
+
result = runner.run()
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The full sample configurations are [`min_example.yaml`](src/mlafactory/examples/min_example.yaml) and [`min_example.json`](src/mlafactory/examples/min_example.json).
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Documentation
|
|
105
|
+
|
|
106
|
+
Additional documentation is available in [`docs/`](docs/):
|
|
107
|
+
|
|
108
|
+
| File | Description |
|
|
109
|
+
|---|---|
|
|
110
|
+
| [`docs/cli.md`](docs/cli.md) | Additional command-line usage notes |
|
|
111
|
+
| [`docs/simulation_model.md`](docs/simulation_model.md) | Simulation architecture and event flow |
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Configuration
|
|
115
|
+
|
|
116
|
+
Use one YAML or JSON configuration file with these top-level sections:
|
|
117
|
+
|
|
118
|
+
- `orders`: mapping of order IDs to product quantities
|
|
119
|
+
- `bom`: products and components, each with a machine `type` and nested `bom`
|
|
120
|
+
- `machines`: machine names, types, setup/cycle times, and optional costs
|
|
121
|
+
- `supplier_lead_times`: raw material reorder delays
|
|
122
|
+
- `inventory_policy_bounds`: `min` and `max` stock limits for every BOM or
|
|
123
|
+
supplier item
|
|
124
|
+
- `initial_inventory`: optional explicit starting stock
|
|
125
|
+
- Optional run settings include `factory_name`, `months`, `hours_per_month`,
|
|
126
|
+
`seed`, `inventory_strategy`, `order_mode`, and `order_mode_params`
|
|
127
|
+
|
|
128
|
+
For complete, valid examples, see [`min_example.yaml`](src/mlafactory/examples/min_example.yaml)
|
|
129
|
+
or [`min_example.json`](src/mlafactory/examples/min_example.json). Machine setup
|
|
130
|
+
and cycle times are expressed in minutes; the simulation duration and reorder
|
|
131
|
+
delays use simulation-time hours.
|
|
132
|
+
|
|
133
|
+
Order interval modes are `fixed`, `random`, `spread`, and `distribution`.
|
|
134
|
+
Distribution mode supports `poisson` and `normal`. The configured seed controls
|
|
135
|
+
random initial inventory and stochastic order intervals.
|
|
136
|
+
|
|
137
|
+
To export CSV reports, set `export_reports: true` in the configuration or pass
|
|
138
|
+
`--export-reports`; choose the destination with `output_dir` or `--output-dir`.
|
|
139
|
+
The CLI options `--print-summary`, `--debug-logs`, and `--export-reports` enable
|
|
140
|
+
their respective outputs.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Project Structure
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
mlafactory/
|
|
148
|
+
├── src/mlafactory/
|
|
149
|
+
│ ├── cli.py # command-line entry point
|
|
150
|
+
│ ├── runner.py # public simulation orchestrator
|
|
151
|
+
│ ├── config/ # configuration, validation, and reporting
|
|
152
|
+
│ ├── examples/ # bundled YAML/JSON configurations
|
|
153
|
+
│ ├── optimization/ # stock-policy optimization adapter
|
|
154
|
+
│ ├── scenario/ # initial inventory and order scheduling
|
|
155
|
+
│ └── sim/ # SimPy simulation entities
|
|
156
|
+
├── docs/
|
|
157
|
+
├── tests/
|
|
158
|
+
└── README.md
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Running Tests
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
pip install -e ".[test]"
|
|
167
|
+
python -m pytest
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
BSD 3-Clause License. See [LICENSE](LICENSE) for details.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Citation
|
|
179
|
+
|
|
180
|
+
To be completed.
|
|
181
|
+
<!--
|
|
182
|
+
If you use mlafactory in your research, please cite:
|
|
183
|
+
|
|
184
|
+
```bibtex
|
|
185
|
+
@article{mlafactory2025,
|
|
186
|
+
title = {mlafactory: A Discrete-Event Simulation Framework for Multi-Level Assembly Systems},
|
|
187
|
+
author = {Your Name},
|
|
188
|
+
journal = {Journal of Open Source Software},
|
|
189
|
+
year = {2025},
|
|
190
|
+
doi = {10.xxxx/joss.xxxxx}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
-->
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Authors
|
|
197
|
+
|
|
198
|
+
Developer and maintainer:
|
|
199
|
+
|
|
200
|
+
**Oscar J. Castro-Lopez**:
|
|
201
|
+
Research Associate, University of Luxembourg
|
|
202
|
+
|
|
203
|
+
Contributors:
|
|
204
|
+
|
|
205
|
+
- **Pierrick Pochelu** DevOps, LuxProvide
|
|
206
|
+
- **Georgios Kafanas** Infrastructure and Architecture Engineer, University of Luxembourg
|
|
207
|
+
|
|
208
|
+
Contributions welcome — please open an issue or pull request on GitLab.
|
|
209
|
+
|
|
210
|
+
## Acknowledgements
|
|
211
|
+
|
|
212
|
+
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,86 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mlafactory"
|
|
7
|
+
version = "0.2.3"
|
|
8
|
+
description = "Digital Multi-Level Assembly (MLA) manufacturing factory simulation made with SimPy"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "BSD-3-Clause"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{name = "Oscar J. Castro-Lopez", email = "oscar.castro@uni.lu" },
|
|
15
|
+
]
|
|
16
|
+
keywords = [
|
|
17
|
+
"simulation", "manufacturing", "factory", "MLA",
|
|
18
|
+
"discrete-event simulation", "simpy",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 3 - Alpha",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Operating System :: OS Independent",
|
|
30
|
+
"Intended Audience :: Science/Research",
|
|
31
|
+
"Topic :: Scientific/Engineering",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
# Lower bounds are PLACEHOLDERS: the `test-lowest` CI job installs exactly these
|
|
35
|
+
# versions on the oldest Python. Raise each one until that job is green.
|
|
36
|
+
dependencies = [
|
|
37
|
+
"simpy>=4.0",
|
|
38
|
+
"numpy>=1.23.2",
|
|
39
|
+
"pandas>=1.5",
|
|
40
|
+
"pyyaml>=6.0.1",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
test = ["pytest>=7", "pytest-cov"]
|
|
45
|
+
dev = ["mlafactory[test]", "ruff==0.15.6"]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
[project.scripts]
|
|
49
|
+
mlafactory = "mlafactory.cli:main"
|
|
50
|
+
|
|
51
|
+
[project.urls]
|
|
52
|
+
Homepage = "https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory"
|
|
53
|
+
Repository = "https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory"
|
|
54
|
+
Documentation = "https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory"
|
|
55
|
+
Issues = "https://gitlab.com/uniluxembourg/hpc/research/cadom/mla_factory/-/issues"
|
|
56
|
+
|
|
57
|
+
[tool.setuptools]
|
|
58
|
+
package-dir = {"" = "src"}
|
|
59
|
+
include-package-data = true
|
|
60
|
+
|
|
61
|
+
[tool.setuptools.packages.find]
|
|
62
|
+
where = ["src"]
|
|
63
|
+
|
|
64
|
+
[tool.setuptools.package-data]
|
|
65
|
+
"mlafactory" = [
|
|
66
|
+
"examples/*.json",
|
|
67
|
+
"examples/*.yaml",
|
|
68
|
+
"examples/individual_files/*.json",
|
|
69
|
+
"minimal_example/*.json",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[tool.pytest.ini_options]
|
|
73
|
+
testpaths = ["tests"]
|
|
74
|
+
addopts = "-ra"
|
|
75
|
+
|
|
76
|
+
[tool.coverage.run]
|
|
77
|
+
source = ["mlafactory"]
|
|
78
|
+
branch = true
|
|
79
|
+
|
|
80
|
+
[tool.ruff]
|
|
81
|
+
target-version = "py311" # flags syntax that would break on the oldest supported Python
|
|
82
|
+
src = ["src"]
|
|
83
|
+
|
|
84
|
+
[tool.ruff.lint]
|
|
85
|
+
select = ["E", "F", "I", "B"]
|
|
86
|
+
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Command-line entry point for running a factory simulation.
|
|
2
|
+
|
|
3
|
+
Precedence of values: command line > config file > defaults.
|
|
4
|
+
Only options explicitly typed on the command line override file values.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from mlafactory.config.arguments import (
|
|
11
|
+
MODULE_FILE_OPTIONS,
|
|
12
|
+
get_args,
|
|
13
|
+
get_default_input_folder,
|
|
14
|
+
)
|
|
15
|
+
from mlafactory.config.config import (
|
|
16
|
+
FactoryConfig,
|
|
17
|
+
RunOptions,
|
|
18
|
+
load_config_file,
|
|
19
|
+
)
|
|
20
|
+
from mlafactory.config.files import InputValidationError, load_json_inputs
|
|
21
|
+
from mlafactory.runner import FactoryRunner
|
|
22
|
+
|
|
23
|
+
# Mapping of CLI flag names to internal OrderScheduleParams field names
|
|
24
|
+
ORDER_PARAM_KEYS = {
|
|
25
|
+
"fixed_interval_hours",
|
|
26
|
+
"random_interval_range",
|
|
27
|
+
"dist_type",
|
|
28
|
+
"poisson_lambda",
|
|
29
|
+
"normal_mean_std",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def process_order_schedule_params(cli_dict: dict[str, Any]) -> dict[str, Any]:
|
|
34
|
+
"""Extract flat order schedule CLI parameters into a nested dict."""
|
|
35
|
+
order_params = {}
|
|
36
|
+
for key in ORDER_PARAM_KEYS:
|
|
37
|
+
if key in cli_dict:
|
|
38
|
+
order_params[key] = cli_dict.pop(key)
|
|
39
|
+
if order_params:
|
|
40
|
+
cli_dict["order_mode_params"] = order_params
|
|
41
|
+
return cli_dict
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def build_runner(cli_overrides: dict[str, Any]) -> FactoryRunner:
|
|
45
|
+
"""Construct FactoryRunner by combining config files, inputs, and CLI overrides."""
|
|
46
|
+
# Extract order schedule CLI flags into nested order_mode_params
|
|
47
|
+
cli_overrides = process_order_schedule_params(cli_overrides)
|
|
48
|
+
|
|
49
|
+
config_file = cli_overrides.pop("factory_config", None)
|
|
50
|
+
|
|
51
|
+
if config_file:
|
|
52
|
+
# Load base configuration from file
|
|
53
|
+
file_data = load_config_file(config_file)
|
|
54
|
+
|
|
55
|
+
# Merge nested order_mode_params if both file and CLI overrides exist
|
|
56
|
+
if "order_mode_params" in cli_overrides and "order_mode_params" in file_data:
|
|
57
|
+
merged_order_params = {
|
|
58
|
+
**file_data["order_mode_params"],
|
|
59
|
+
**cli_overrides["order_mode_params"],
|
|
60
|
+
}
|
|
61
|
+
cli_overrides["order_mode_params"] = merged_order_params
|
|
62
|
+
|
|
63
|
+
if cli_overrides:
|
|
64
|
+
_announce(config_file, cli_overrides)
|
|
65
|
+
|
|
66
|
+
# CLI overrides take precedence over config file
|
|
67
|
+
data = {**file_data, **cli_overrides}
|
|
68
|
+
else:
|
|
69
|
+
# Load inputs from directory
|
|
70
|
+
input_folder = cli_overrides.pop("input_folder", get_default_input_folder())
|
|
71
|
+
inputs = load_json_inputs(input_folder, cli_overrides, MODULE_FILE_OPTIONS)
|
|
72
|
+
|
|
73
|
+
# Combine JSON folder inputs with explicit CLI overrides
|
|
74
|
+
data = {**inputs, **cli_overrides}
|
|
75
|
+
|
|
76
|
+
# Instantiate dataclasses cleanly
|
|
77
|
+
factory_config = FactoryConfig.from_dict(data)
|
|
78
|
+
run_options = RunOptions.from_dict(data)
|
|
79
|
+
|
|
80
|
+
return FactoryRunner(factory_config, run_options)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _announce(config_file: str, overrides: dict[str, Any]) -> None:
|
|
84
|
+
"""Notify user of CLI overrides taking precedence over configuration file."""
|
|
85
|
+
shown = ", ".join(f"{key}={value}" for key, value in overrides.items())
|
|
86
|
+
print(
|
|
87
|
+
f"mlafactory: using {config_file}; command-line overrides applied: {shown}",
|
|
88
|
+
file=sys.stderr,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def main(argv=None) -> int:
|
|
93
|
+
"""Run the factory simulation from CLI arguments or a config file."""
|
|
94
|
+
cli_overrides = {}
|
|
95
|
+
try:
|
|
96
|
+
cli_overrides = get_args(argv)
|
|
97
|
+
runner = build_runner(cli_overrides)
|
|
98
|
+
runner.run()
|
|
99
|
+
except (InputValidationError, FileNotFoundError, ValueError) as error:
|
|
100
|
+
if cli_overrides.get("debug_logs"):
|
|
101
|
+
raise
|
|
102
|
+
print(f"mlafactory: error: {error}", file=sys.stderr)
|
|
103
|
+
return 1
|
|
104
|
+
return 0
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
raise SystemExit(main())
|