discopt-doe 0.2.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.
Files changed (62) hide show
  1. discopt_doe-0.2.0/PKG-INFO +203 -0
  2. discopt_doe-0.2.0/README.md +177 -0
  3. discopt_doe-0.2.0/pyproject.toml +97 -0
  4. discopt_doe-0.2.0/setup.cfg +4 -0
  5. discopt_doe-0.2.0/src/discopt/doe/__init__.py +282 -0
  6. discopt_doe-0.2.0/src/discopt/doe/acquisition.py +221 -0
  7. discopt_doe-0.2.0/src/discopt/doe/anova.py +399 -0
  8. discopt_doe-0.2.0/src/discopt/doe/cli.py +2220 -0
  9. discopt_doe-0.2.0/src/discopt/doe/design.py +1168 -0
  10. discopt_doe-0.2.0/src/discopt/doe/discrimination.py +840 -0
  11. discopt_doe-0.2.0/src/discopt/doe/discrimination_sequential.py +243 -0
  12. discopt_doe-0.2.0/src/discopt/doe/estimability.py +394 -0
  13. discopt_doe-0.2.0/src/discopt/doe/exploration.py +225 -0
  14. discopt_doe-0.2.0/src/discopt/doe/fim.py +953 -0
  15. discopt_doe-0.2.0/src/discopt/doe/fractional.py +363 -0
  16. discopt_doe-0.2.0/src/discopt/doe/gui/__init__.py +6 -0
  17. discopt_doe-0.2.0/src/discopt/doe/gui/app.py +2342 -0
  18. discopt_doe-0.2.0/src/discopt/doe/gui/discopt-logo.png +0 -0
  19. discopt_doe-0.2.0/src/discopt/doe/gui/launcher.py +142 -0
  20. discopt_doe-0.2.0/src/discopt/doe/install.py +71 -0
  21. discopt_doe-0.2.0/src/discopt/doe/latin.py +405 -0
  22. discopt_doe-0.2.0/src/discopt/doe/model_based.py +549 -0
  23. discopt_doe-0.2.0/src/discopt/doe/optimize.py +366 -0
  24. discopt_doe-0.2.0/src/discopt/doe/profile.py +426 -0
  25. discopt_doe-0.2.0/src/discopt/doe/screening.py +352 -0
  26. discopt_doe-0.2.0/src/discopt/doe/selection.py +391 -0
  27. discopt_doe-0.2.0/src/discopt/doe/sequential.py +225 -0
  28. discopt_doe-0.2.0/src/discopt/doe/skill/SKILL.md +169 -0
  29. discopt_doe-0.2.0/src/discopt/doe/skill/agents/doe-expert.md +83 -0
  30. discopt_doe-0.2.0/src/discopt/doe/skill/agents/estimability-expert.md +125 -0
  31. discopt_doe-0.2.0/src/discopt/doe/skill/agents/identifiability-expert.md +111 -0
  32. discopt_doe-0.2.0/src/discopt/doe/skill/agents/model-discrimination-expert.md +138 -0
  33. discopt_doe-0.2.0/src/discopt/doe/surrogate.py +299 -0
  34. discopt_doe-0.2.0/src/discopt/doe/templates.py +623 -0
  35. discopt_doe-0.2.0/src/discopt/doe/workbook.py +794 -0
  36. discopt_doe-0.2.0/src/discopt_doe.egg-info/PKG-INFO +203 -0
  37. discopt_doe-0.2.0/src/discopt_doe.egg-info/SOURCES.txt +60 -0
  38. discopt_doe-0.2.0/src/discopt_doe.egg-info/dependency_links.txt +1 -0
  39. discopt_doe-0.2.0/src/discopt_doe.egg-info/entry_points.txt +5 -0
  40. discopt_doe-0.2.0/src/discopt_doe.egg-info/requires.txt +14 -0
  41. discopt_doe-0.2.0/src/discopt_doe.egg-info/top_level.txt +1 -0
  42. discopt_doe-0.2.0/tests/test_batch_doe.py +436 -0
  43. discopt_doe-0.2.0/tests/test_discrimination_criteria.py +447 -0
  44. discopt_doe-0.2.0/tests/test_discrimination_examples.py +288 -0
  45. discopt_doe-0.2.0/tests/test_discrimination_sequential.py +287 -0
  46. discopt_doe-0.2.0/tests/test_doe.py +377 -0
  47. discopt_doe-0.2.0/tests/test_doe_cli.py +873 -0
  48. discopt_doe-0.2.0/tests/test_doe_fractional.py +237 -0
  49. discopt_doe-0.2.0/tests/test_doe_gui.py +257 -0
  50. discopt_doe-0.2.0/tests/test_doe_latin.py +489 -0
  51. discopt_doe-0.2.0/tests/test_doe_model_based.py +427 -0
  52. discopt_doe-0.2.0/tests/test_doe_optimize.py +431 -0
  53. discopt_doe-0.2.0/tests/test_estimability.py +199 -0
  54. discopt_doe-0.2.0/tests/test_fim.py +535 -0
  55. discopt_doe-0.2.0/tests/test_identifiability.py +249 -0
  56. discopt_doe-0.2.0/tests/test_identifiability_edge_cases.py +327 -0
  57. discopt_doe-0.2.0/tests/test_install.py +49 -0
  58. discopt_doe-0.2.0/tests/test_langmuir_batch_reactor.py +260 -0
  59. discopt_doe-0.2.0/tests/test_model_selection.py +298 -0
  60. discopt_doe-0.2.0/tests/test_plugin.py +53 -0
  61. discopt_doe-0.2.0/tests/test_profile.py +232 -0
  62. discopt_doe-0.2.0/tests/test_sequential_doe.py +227 -0
@@ -0,0 +1,203 @@
1
+ Metadata-Version: 2.4
2
+ Name: discopt-doe
3
+ Version: 0.2.0
4
+ Summary: Design-of-experiments plugin for the discopt modeling language
5
+ Author-email: John Kitchin <jkitchin@andrew.cmu.edu>
6
+ License: EPL-2.0
7
+ Project-URL: Homepage, https://github.com/jkitchin/discopt-doe
8
+ Project-URL: Documentation, https://jkitchin.github.io/discopt-doe/
9
+ Project-URL: Repository, https://github.com/jkitchin/discopt-doe
10
+ Project-URL: Issues, https://github.com/jkitchin/discopt-doe/issues
11
+ Project-URL: Changelog, https://github.com/jkitchin/discopt-doe/blob/main/CHANGELOG.md
12
+ Requires-Python: >=3.10
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: discopt>=0.6
15
+ Requires-Dist: jax>=0.4
16
+ Requires-Dist: numpy>=1.24
17
+ Requires-Dist: scipy>=1.10
18
+ Requires-Dist: openpyxl>=3.1
19
+ Provides-Extra: gui
20
+ Requires-Dist: streamlit>=1.49; extra == "gui"
21
+ Requires-Dist: pandas>=2.0; extra == "gui"
22
+ Requires-Dist: matplotlib>=3.5; extra == "gui"
23
+ Requires-Dist: scikit-learn>=1.0; extra == "gui"
24
+ Provides-Extra: ml
25
+ Requires-Dist: scikit-learn>=1.0; extra == "ml"
26
+
27
+ # discopt-doe
28
+
29
+ ![discopt-doe banner](docs/doe-banner.png)
30
+
31
+ [![ci](https://github.com/jkitchin/discopt-doe/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/jkitchin/discopt-doe/actions/workflows/ci.yml)
32
+
33
+ Design-of-experiments plugin for the [discopt](https://github.com/jkitchin/discopt)
34
+ modeling language. Installs as the `discopt.doe` namespace package — code written
35
+ against `from discopt.doe import ...` works unchanged.
36
+
37
+ Three complementary entry points:
38
+
39
+ 1. **"What is the best operating condition?"** — active-learning optimization:
40
+ fit a surrogate to completed experiments, recommend the next batch via an
41
+ acquisition function (EI, UCB, steepest ascent), track everything in an
42
+ Excel workbook.
43
+ 2. **"Does this factor matter?"** — classical designs: 2-level full/fractional
44
+ factorials, mixture designs, Latin/Graeco-Latin squares, main-effect
45
+ estimates, ANOVA.
46
+ 3. **"How precisely can I estimate the model parameters?"** — model-based DoE:
47
+ exact D/A/E-optimal design from the Fisher Information Matrix (JAX
48
+ autodiff), identifiability/estimability diagnostics, profile likelihood,
49
+ model discrimination, sequential estimate–design loops.
50
+
51
+ Parameter estimation (`discopt.estimate`) lives in the base package; both
52
+ share the same `Experiment` interface.
53
+
54
+ ## Install
55
+
56
+ Its `discopt>=0.6` dependency is on PyPI, so both a from-source install and a
57
+ direct git install resolve without any extra steps.
58
+
59
+ > **Not yet on PyPI:** `discopt-doe` itself has not been published yet, so the
60
+ > plain `pip install discopt-doe` form below works only once the first release
61
+ > is cut. Until then, install from source or git.
62
+
63
+ Recommended (uv):
64
+
65
+ ```bash
66
+ git clone https://github.com/jkitchin/discopt-doe
67
+ cd discopt-doe
68
+ uv sync --all-extras # core + gui + ml + dev
69
+ ```
70
+
71
+ With pip, straight from git:
72
+
73
+ ```bash
74
+ pip install "git+https://github.com/jkitchin/discopt-doe" # core
75
+ pip install "git+https://github.com/jkitchin/discopt-doe#egg=discopt-doe[gui]" # + GUI
76
+ ```
77
+
78
+ Once `discopt-doe` is published, the usual form applies:
79
+
80
+ ```bash
81
+ pip install discopt-doe # core
82
+ pip install "discopt-doe[gui]" # + Streamlit workbook GUI
83
+ pip install "discopt-doe[ml]" # + scikit-learn surrogates
84
+ ```
85
+
86
+ Requires `discopt>=0.6` (the first release with the public
87
+ `discopt.parametric` API and the CLI plugin hook).
88
+
89
+ ## Quick start
90
+
91
+ FIM-based optimal design:
92
+
93
+ ```python
94
+ from discopt.doe import compute_fim, optimal_experiment, DesignCriterion
95
+
96
+ fim = compute_fim(experiment, param_values={"k": 2.0}, design_values={"T": 350.0})
97
+ design = optimal_experiment(
98
+ experiment,
99
+ param_values={"k": 2.0},
100
+ design_bounds={"T": (300, 400)},
101
+ criterion=DesignCriterion.D_OPTIMAL,
102
+ )
103
+ print(design.summary())
104
+ ```
105
+
106
+ Active-learning round against a workbook:
107
+
108
+ ```python
109
+ from discopt.doe import optimize_round, OptimizationCriterion
110
+
111
+ result = optimize_round(
112
+ workbook="opt.xlsx",
113
+ criterion=OptimizationCriterion.MAXIMIZE,
114
+ surrogate="gp",
115
+ acquisition="expected_improvement",
116
+ batch_size=4,
117
+ )
118
+ print(result.next_designs)
119
+ ```
120
+
121
+ Identifiability diagnostics before you spend beam time:
122
+
123
+ ```python
124
+ from discopt.doe import diagnose_identifiability, estimability_rank
125
+
126
+ diag = diagnose_identifiability(experiment, param_values)
127
+ est = estimability_rank(experiment, param_values)
128
+ ```
129
+
130
+ ## Command line
131
+
132
+ Installing this package adds the `doe` subcommand to the base discopt CLI
133
+ (via the `"discopt.cli"` entry-point group):
134
+
135
+ ```bash
136
+ discopt doe templates # list workbook templates
137
+ discopt doe new linear -o run.xlsx --input T:300:400 --n 8
138
+ discopt doe status run.xlsx
139
+ discopt doe fit run.xlsx # fit parameters to completed rows
140
+ discopt doe anova run.xlsx # ANOVA F-table (latin/factorial designs)
141
+ discopt doe extend run.xlsx --n 4 # design the next batch
142
+ discopt doe optimize run.xlsx # one active-learning round (optimize template)
143
+ discopt doe gui run.xlsx # Streamlit GUI (needs [gui] extra)
144
+ ```
145
+
146
+ ## GUI
147
+
148
+ `discopt doe gui [workbook.xlsx]` launches a Streamlit app over a campaign
149
+ workbook (install the `[gui]` extra, which also pulls scikit-learn for the
150
+ active-learning round). It wraps the same `do_*` functions as the CLI:
151
+
152
+ - **Create** a new campaign from a template, browsing to an output folder.
153
+ - **Edit responses** in-app or in Excel, then Save; the **Rename** panel can
154
+ rename factors/response — note this clears the fit artifacts, so re-run Fit.
155
+ - **Fit / Extend / Optimize / ANOVA** panels drive the corresponding verb, and
156
+ a **History** panel shows the workbook's audit log.
157
+
158
+ Flags: `--port N`, `--no-browser`. The `DISCOPT_DOE_WORKBOOK` environment
159
+ variable pre-selects a workbook. Keep charts in a separate file — the CLI/GUI
160
+ rewrite the workbook and openpyxl does not preserve embedded charts (a `.bak`
161
+ is written before the first save).
162
+
163
+ ## Development
164
+
165
+ The project is uv-managed:
166
+
167
+ ```bash
168
+ uv sync --all-extras # create .venv with everything
169
+ uv run pytest # fast test set (slow tests excluded by default)
170
+ uv run pytest -m '' # everything
171
+ ```
172
+
173
+ To develop against a local discopt checkout instead of the PyPI release, add
174
+ a `[tool.uv.sources]` override pointing `discopt` at your editable clone:
175
+
176
+ ```toml
177
+ [tool.uv.sources]
178
+ discopt = { path = "../../projects/discopt", editable = true }
179
+ ```
180
+
181
+ Docs are a Jupyter Book:
182
+
183
+ ```bash
184
+ uv run jupyter-book build docs/
185
+ ```
186
+
187
+ ## Claude Code skill
188
+
189
+ The package bundles a `/discopt-doe` skill and four expert agents (DoE,
190
+ estimability, identifiability, model discrimination) for Claude Code:
191
+
192
+ ```bash
193
+ discopt-doe-install-skill # install to ~/.claude
194
+ discopt-doe-install-skill --project # install to ./.claude (versioned)
195
+ ```
196
+
197
+ ## Literature
198
+
199
+ The methods implemented here are referenced throughout the docs; the full
200
+ bibliography is in [docs/references.bib](docs/references.bib) (Atkinson &
201
+ Donev optimal design, Franceschini & Macchietto MBDoE, Yao estimability,
202
+ Raue profile likelihood, Hunter–Reiner/Buzzi-Ferraris discrimination, and
203
+ more).
@@ -0,0 +1,177 @@
1
+ # discopt-doe
2
+
3
+ ![discopt-doe banner](docs/doe-banner.png)
4
+
5
+ [![ci](https://github.com/jkitchin/discopt-doe/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/jkitchin/discopt-doe/actions/workflows/ci.yml)
6
+
7
+ Design-of-experiments plugin for the [discopt](https://github.com/jkitchin/discopt)
8
+ modeling language. Installs as the `discopt.doe` namespace package — code written
9
+ against `from discopt.doe import ...` works unchanged.
10
+
11
+ Three complementary entry points:
12
+
13
+ 1. **"What is the best operating condition?"** — active-learning optimization:
14
+ fit a surrogate to completed experiments, recommend the next batch via an
15
+ acquisition function (EI, UCB, steepest ascent), track everything in an
16
+ Excel workbook.
17
+ 2. **"Does this factor matter?"** — classical designs: 2-level full/fractional
18
+ factorials, mixture designs, Latin/Graeco-Latin squares, main-effect
19
+ estimates, ANOVA.
20
+ 3. **"How precisely can I estimate the model parameters?"** — model-based DoE:
21
+ exact D/A/E-optimal design from the Fisher Information Matrix (JAX
22
+ autodiff), identifiability/estimability diagnostics, profile likelihood,
23
+ model discrimination, sequential estimate–design loops.
24
+
25
+ Parameter estimation (`discopt.estimate`) lives in the base package; both
26
+ share the same `Experiment` interface.
27
+
28
+ ## Install
29
+
30
+ Its `discopt>=0.6` dependency is on PyPI, so both a from-source install and a
31
+ direct git install resolve without any extra steps.
32
+
33
+ > **Not yet on PyPI:** `discopt-doe` itself has not been published yet, so the
34
+ > plain `pip install discopt-doe` form below works only once the first release
35
+ > is cut. Until then, install from source or git.
36
+
37
+ Recommended (uv):
38
+
39
+ ```bash
40
+ git clone https://github.com/jkitchin/discopt-doe
41
+ cd discopt-doe
42
+ uv sync --all-extras # core + gui + ml + dev
43
+ ```
44
+
45
+ With pip, straight from git:
46
+
47
+ ```bash
48
+ pip install "git+https://github.com/jkitchin/discopt-doe" # core
49
+ pip install "git+https://github.com/jkitchin/discopt-doe#egg=discopt-doe[gui]" # + GUI
50
+ ```
51
+
52
+ Once `discopt-doe` is published, the usual form applies:
53
+
54
+ ```bash
55
+ pip install discopt-doe # core
56
+ pip install "discopt-doe[gui]" # + Streamlit workbook GUI
57
+ pip install "discopt-doe[ml]" # + scikit-learn surrogates
58
+ ```
59
+
60
+ Requires `discopt>=0.6` (the first release with the public
61
+ `discopt.parametric` API and the CLI plugin hook).
62
+
63
+ ## Quick start
64
+
65
+ FIM-based optimal design:
66
+
67
+ ```python
68
+ from discopt.doe import compute_fim, optimal_experiment, DesignCriterion
69
+
70
+ fim = compute_fim(experiment, param_values={"k": 2.0}, design_values={"T": 350.0})
71
+ design = optimal_experiment(
72
+ experiment,
73
+ param_values={"k": 2.0},
74
+ design_bounds={"T": (300, 400)},
75
+ criterion=DesignCriterion.D_OPTIMAL,
76
+ )
77
+ print(design.summary())
78
+ ```
79
+
80
+ Active-learning round against a workbook:
81
+
82
+ ```python
83
+ from discopt.doe import optimize_round, OptimizationCriterion
84
+
85
+ result = optimize_round(
86
+ workbook="opt.xlsx",
87
+ criterion=OptimizationCriterion.MAXIMIZE,
88
+ surrogate="gp",
89
+ acquisition="expected_improvement",
90
+ batch_size=4,
91
+ )
92
+ print(result.next_designs)
93
+ ```
94
+
95
+ Identifiability diagnostics before you spend beam time:
96
+
97
+ ```python
98
+ from discopt.doe import diagnose_identifiability, estimability_rank
99
+
100
+ diag = diagnose_identifiability(experiment, param_values)
101
+ est = estimability_rank(experiment, param_values)
102
+ ```
103
+
104
+ ## Command line
105
+
106
+ Installing this package adds the `doe` subcommand to the base discopt CLI
107
+ (via the `"discopt.cli"` entry-point group):
108
+
109
+ ```bash
110
+ discopt doe templates # list workbook templates
111
+ discopt doe new linear -o run.xlsx --input T:300:400 --n 8
112
+ discopt doe status run.xlsx
113
+ discopt doe fit run.xlsx # fit parameters to completed rows
114
+ discopt doe anova run.xlsx # ANOVA F-table (latin/factorial designs)
115
+ discopt doe extend run.xlsx --n 4 # design the next batch
116
+ discopt doe optimize run.xlsx # one active-learning round (optimize template)
117
+ discopt doe gui run.xlsx # Streamlit GUI (needs [gui] extra)
118
+ ```
119
+
120
+ ## GUI
121
+
122
+ `discopt doe gui [workbook.xlsx]` launches a Streamlit app over a campaign
123
+ workbook (install the `[gui]` extra, which also pulls scikit-learn for the
124
+ active-learning round). It wraps the same `do_*` functions as the CLI:
125
+
126
+ - **Create** a new campaign from a template, browsing to an output folder.
127
+ - **Edit responses** in-app or in Excel, then Save; the **Rename** panel can
128
+ rename factors/response — note this clears the fit artifacts, so re-run Fit.
129
+ - **Fit / Extend / Optimize / ANOVA** panels drive the corresponding verb, and
130
+ a **History** panel shows the workbook's audit log.
131
+
132
+ Flags: `--port N`, `--no-browser`. The `DISCOPT_DOE_WORKBOOK` environment
133
+ variable pre-selects a workbook. Keep charts in a separate file — the CLI/GUI
134
+ rewrite the workbook and openpyxl does not preserve embedded charts (a `.bak`
135
+ is written before the first save).
136
+
137
+ ## Development
138
+
139
+ The project is uv-managed:
140
+
141
+ ```bash
142
+ uv sync --all-extras # create .venv with everything
143
+ uv run pytest # fast test set (slow tests excluded by default)
144
+ uv run pytest -m '' # everything
145
+ ```
146
+
147
+ To develop against a local discopt checkout instead of the PyPI release, add
148
+ a `[tool.uv.sources]` override pointing `discopt` at your editable clone:
149
+
150
+ ```toml
151
+ [tool.uv.sources]
152
+ discopt = { path = "../../projects/discopt", editable = true }
153
+ ```
154
+
155
+ Docs are a Jupyter Book:
156
+
157
+ ```bash
158
+ uv run jupyter-book build docs/
159
+ ```
160
+
161
+ ## Claude Code skill
162
+
163
+ The package bundles a `/discopt-doe` skill and four expert agents (DoE,
164
+ estimability, identifiability, model discrimination) for Claude Code:
165
+
166
+ ```bash
167
+ discopt-doe-install-skill # install to ~/.claude
168
+ discopt-doe-install-skill --project # install to ./.claude (versioned)
169
+ ```
170
+
171
+ ## Literature
172
+
173
+ The methods implemented here are referenced throughout the docs; the full
174
+ bibliography is in [docs/references.bib](docs/references.bib) (Atkinson &
175
+ Donev optimal design, Franceschini & Macchietto MBDoE, Yao estimability,
176
+ Raue profile likelihood, Hunter–Reiner/Buzzi-Ferraris discrimination, and
177
+ more).
@@ -0,0 +1,97 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "discopt-doe"
7
+ version = "0.2.0"
8
+ description = "Design-of-experiments plugin for the discopt modeling language"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "EPL-2.0" }
12
+ authors = [{ name = "John Kitchin", email = "jkitchin@andrew.cmu.edu" }]
13
+ dependencies = [
14
+ # Public parametric-compile API + the "discopt.cli" plugin hook land in 0.6.
15
+ "discopt>=0.6",
16
+ "jax>=0.4", # fim.py / model_based.py use jax directly
17
+ "numpy>=1.24",
18
+ "scipy>=1.10",
19
+ "openpyxl>=3.1", # workbook.py and the `discopt doe` CLI verbs
20
+ ]
21
+
22
+ [project.urls]
23
+ Homepage = "https://github.com/jkitchin/discopt-doe"
24
+ Documentation = "https://jkitchin.github.io/discopt-doe/"
25
+ Repository = "https://github.com/jkitchin/discopt-doe"
26
+ Issues = "https://github.com/jkitchin/discopt-doe/issues"
27
+ Changelog = "https://github.com/jkitchin/discopt-doe/blob/main/CHANGELOG.md"
28
+
29
+ [project.optional-dependencies]
30
+ # The GUI needs matplotlib (history / surrogate diagnostic plots) and
31
+ # scikit-learn (its optimize round fits a GP surrogate), so the gui extra
32
+ # pulls in the ml extra's dependency too.
33
+ # streamlit >= 1.49: the app uses st.logo (added 1.35) and the width="stretch"
34
+ # element API (string width literals, ~1.49); older versions crash at startup.
35
+ gui = ["streamlit>=1.49", "pandas>=2.0", "matplotlib>=3.5", "scikit-learn>=1.0"]
36
+ ml = ["scikit-learn>=1.0"] # surrogate.py sklearn estimators
37
+
38
+ [project.scripts]
39
+ discopt-doe-install-skill = "discopt.doe.install:main"
40
+
41
+ # The base discopt CLI discovers plugin subcommands through this group (see
42
+ # the protocol in discopt/cli.py): the entry-point name is the subcommand and
43
+ # the value is a module exposing add_subparser(subparsers) and run(args).
44
+ # This is what keeps `discopt doe ...` working after the extraction.
45
+ [project.entry-points."discopt.cli"]
46
+ doe = "discopt.doe.cli"
47
+
48
+ [dependency-groups]
49
+ dev = [
50
+ "pytest>=8",
51
+ "pytest-timeout",
52
+ # tutorial notebooks and exploration.plot_* use matplotlib
53
+ "matplotlib>=3.5",
54
+ # notebook build scripts (scripts/build_*_notebook.py)
55
+ "nbformat>=5",
56
+ "nbclient>=0.10",
57
+ "ipykernel>=6",
58
+ # docs build
59
+ "jupyter-book<2",
60
+ "sphinxcontrib-bibtex",
61
+ # lint/format hooks (see .pre-commit-config.yaml)
62
+ "pre-commit>=3",
63
+ ]
64
+
65
+ # discopt.doe is a PEP 420 namespace subpackage: it merges into the ``discopt``
66
+ # namespace at import time (discopt's __init__ extends its __path__ via
67
+ # pkgutil.extend_path). We deliberately package only ``discopt.doe`` — never
68
+ # ``discopt`` — so this distribution never shadows the base package.
69
+ [tool.setuptools.packages.find]
70
+ where = ["src"]
71
+ include = ["discopt.doe*"]
72
+ namespaces = true
73
+
74
+ [tool.setuptools.package-data]
75
+ "discopt.doe" = ["gui/discopt-logo.png", "skill/SKILL.md", "skill/agents/*.md"]
76
+
77
+ [tool.pytest.ini_options]
78
+ testpaths = ["tests"]
79
+ timeout = 300
80
+ addopts = "-m 'not slow'"
81
+ markers = [
82
+ "smoke: one solve per code path on a tiny instance; fast",
83
+ "slow: long-running tests (excluded by default; run with -m '')",
84
+ "integration: end-to-end multi-component workflows",
85
+ ]
86
+
87
+ [tool.ruff]
88
+ line-length = 100
89
+ target-version = "py310"
90
+ # The docs notebooks are demonstrative (and several are generated by
91
+ # scripts/build_*_notebook.py); their idiomatic style (`plt.show();`,
92
+ # mid-cell imports) should not gate commits, so keep them out of lint/format.
93
+ extend-exclude = ["docs/notebooks"]
94
+
95
+ [tool.ruff.lint.per-file-ignores]
96
+ # The discopt version guard must run before the API re-exports.
97
+ "src/discopt/doe/__init__.py" = ["E402"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+