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.
Files changed (69) hide show
  1. {mlafactory-0.1.2 → mlafactory-0.2.3}/MANIFEST.in +1 -0
  2. mlafactory-0.2.3/PKG-INFO +247 -0
  3. mlafactory-0.2.3/README.md +212 -0
  4. mlafactory-0.2.3/pyproject.toml +86 -0
  5. mlafactory-0.2.3/src/mlafactory/__init__.py +5 -0
  6. mlafactory-0.2.3/src/mlafactory/cli.py +108 -0
  7. mlafactory-0.2.3/src/mlafactory/config/arguments.py +288 -0
  8. mlafactory-0.2.3/src/mlafactory/config/bom.py +41 -0
  9. mlafactory-0.2.3/src/mlafactory/config/config.py +181 -0
  10. mlafactory-0.2.3/src/mlafactory/config/files.py +39 -0
  11. mlafactory-0.2.3/src/mlafactory/config/intervals.py +78 -0
  12. mlafactory-0.2.3/src/mlafactory/config/objectives.py +77 -0
  13. mlafactory-0.1.2/src/mlafactory/aux_reports.py → mlafactory-0.2.3/src/mlafactory/config/reports.py +66 -51
  14. mlafactory-0.2.3/src/mlafactory/config/result.py +228 -0
  15. mlafactory-0.2.3/src/mlafactory/config/validation.py +155 -0
  16. {mlafactory-0.1.2/src/mlafactory/minimal_example → mlafactory-0.2.3/src/mlafactory/examples/individual_files}/bom.json +34 -26
  17. 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
  18. mlafactory-0.2.3/src/mlafactory/examples/individual_files/machines.json +5 -0
  19. mlafactory-0.2.3/src/mlafactory/examples/individual_files/orders.json +14 -0
  20. 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
  21. mlafactory-0.2.3/src/mlafactory/examples/min_example.json +287 -0
  22. mlafactory-0.2.3/src/mlafactory/examples/min_example.yaml +112 -0
  23. mlafactory-0.2.3/src/mlafactory/optimization/optimize_stock_policy.py +54 -0
  24. mlafactory-0.2.3/src/mlafactory/optimization/stock_policy_problem.py +209 -0
  25. mlafactory-0.2.3/src/mlafactory/runner.py +233 -0
  26. mlafactory-0.2.3/src/mlafactory/scenario/initial_inventory.py +59 -0
  27. mlafactory-0.2.3/src/mlafactory/scenario/orders.py +65 -0
  28. mlafactory-0.2.3/src/mlafactory/sim/__init__.py +0 -0
  29. mlafactory-0.1.2/src/mlafactory/MachineDispatcher.py → mlafactory-0.2.3/src/mlafactory/sim/dispatcher.py +15 -13
  30. mlafactory-0.1.2/src/mlafactory/Machine.py → mlafactory-0.2.3/src/mlafactory/sim/machine.py +13 -2
  31. mlafactory-0.1.2/src/mlafactory/FactorySimulator.py → mlafactory-0.2.3/src/mlafactory/sim/simulator.py +91 -69
  32. mlafactory-0.1.2/src/mlafactory/Inventory.py → mlafactory-0.2.3/src/mlafactory/sim/stock.py +13 -9
  33. mlafactory-0.2.3/src/mlafactory.egg-info/PKG-INFO +247 -0
  34. mlafactory-0.2.3/src/mlafactory.egg-info/SOURCES.txt +52 -0
  35. mlafactory-0.2.3/src/mlafactory.egg-info/entry_points.txt +2 -0
  36. mlafactory-0.2.3/src/mlafactory.egg-info/requires.txt +12 -0
  37. mlafactory-0.2.3/tests/test_arguments.py +159 -0
  38. mlafactory-0.2.3/tests/test_bike_integration.py +114 -0
  39. mlafactory-0.2.3/tests/test_cli.py +195 -0
  40. mlafactory-0.2.3/tests/test_config.py +246 -0
  41. mlafactory-0.2.3/tests/test_des_scenarios.py +94 -0
  42. mlafactory-0.2.3/tests/test_intervals_objectives.py +127 -0
  43. mlafactory-0.2.3/tests/test_result.py +195 -0
  44. mlafactory-0.2.3/tests/test_runner_run.py +152 -0
  45. mlafactory-0.2.3/tests/test_stock_policy_problem.py +29 -0
  46. mlafactory-0.2.3/tests/test_validation.py +161 -0
  47. mlafactory-0.1.2/PKG-INFO +0 -336
  48. mlafactory-0.1.2/README.md +0 -312
  49. mlafactory-0.1.2/pyproject.toml +0 -53
  50. mlafactory-0.1.2/src/mlafactory/FactoryRunner.py +0 -411
  51. mlafactory-0.1.2/src/mlafactory/aux_arguments.py +0 -229
  52. mlafactory-0.1.2/src/mlafactory/aux_files.py +0 -42
  53. mlafactory-0.1.2/src/mlafactory/aux_intervals.py +0 -75
  54. mlafactory-0.1.2/src/mlafactory/minimal_example/orders_demand.json +0 -12
  55. mlafactory-0.1.2/src/mlafactory/run_factory.py +0 -48
  56. mlafactory-0.1.2/src/mlafactory.egg-info/PKG-INFO +0 -336
  57. mlafactory-0.1.2/src/mlafactory.egg-info/SOURCES.txt +0 -30
  58. mlafactory-0.1.2/src/mlafactory.egg-info/entry_points.txt +0 -2
  59. mlafactory-0.1.2/src/mlafactory.egg-info/requires.txt +0 -4
  60. mlafactory-0.1.2/tests/test_mlafactory.py +0 -819
  61. mlafactory-0.1.2/tests/test_run_factory.py +0 -113
  62. {mlafactory-0.1.2 → mlafactory-0.2.3}/LICENSE +0 -0
  63. {mlafactory-0.1.2 → mlafactory-0.2.3}/setup.cfg +0 -0
  64. {mlafactory-0.1.2/src/mlafactory → mlafactory-0.2.3/src/mlafactory/config}/__init__.py +0 -0
  65. {mlafactory-0.1.2/src/mlafactory/minimal_example → mlafactory-0.2.3/src/mlafactory/examples/individual_files}/initial_inventory.json +0 -0
  66. /mlafactory-0.1.2/src/mlafactory/minimal_example/machines.json → /mlafactory-0.2.3/src/mlafactory/examples/individual_files/machines copy.json +0 -0
  67. {mlafactory-0.1.2/src/mlafactory/minimal_example → mlafactory-0.2.3/src/mlafactory/scenario}/__init__.py +0 -0
  68. {mlafactory-0.1.2 → mlafactory-0.2.3}/src/mlafactory.egg-info/dependency_links.txt +0 -0
  69. {mlafactory-0.1.2 → mlafactory-0.2.3}/src/mlafactory.egg-info/top_level.txt +0 -0
@@ -1 +1,2 @@
1
1
  recursive-include src/mlafactory/minimal_example *.json
2
+ recursive-include src/mlafactory/examples *.json *.yaml
@@ -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
+ [![PyPI version](https://badge.fury.io/py/mlafactory.svg)](https://badge.fury.io/py/mlafactory)
39
+ [![License: BSD-3](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
40
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](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
+ [![PyPI version](https://badge.fury.io/py/mlafactory.svg)](https://badge.fury.io/py/mlafactory)
4
+ [![License: BSD-3](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
5
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](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,5 @@
1
+ """Public package interface for mlafactory."""
2
+
3
+ from .runner import FactoryRunner
4
+
5
+ __all__ = ["FactoryRunner"]
@@ -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())