pinf 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.
Files changed (48) hide show
  1. pinf-0.1.0/LICENSE +21 -0
  2. pinf-0.1.0/PKG-INFO +418 -0
  3. pinf-0.1.0/README.md +373 -0
  4. pinf-0.1.0/pyproject.toml +74 -0
  5. pinf-0.1.0/setup.cfg +4 -0
  6. pinf-0.1.0/src/pinf/__init__.py +5 -0
  7. pinf-0.1.0/src/pinf/execution_engine.py +780 -0
  8. pinf-0.1.0/src/pinf/gui/__init__.py +1 -0
  9. pinf-0.1.0/src/pinf/gui/app.py +946 -0
  10. pinf-0.1.0/src/pinf/gui/helpers.py +488 -0
  11. pinf-0.1.0/src/pinf/gui/launcher.py +37 -0
  12. pinf-0.1.0/src/pinf/gui/seeded_data/pi_simulation_bounds_s2_m1.csv +6 -0
  13. pinf-0.1.0/src/pinf/gui/seeded_data/pi_simulation_bounds_s2_m2.csv +7 -0
  14. pinf-0.1.0/src/pinf/gui/seeded_data/pi_simulation_stats_s2_m1.csv +6 -0
  15. pinf-0.1.0/src/pinf/gui/seeded_data/pi_simulation_stats_s2_m2.csv +7 -0
  16. pinf-0.1.0/src/pinf/gui/seeded_data/pi_subset_s2.csv +8 -0
  17. pinf-0.1.0/src/pinf/gui/seeded_data/pi_subset_s2_m2.csv +8 -0
  18. pinf-0.1.0/src/pinf/gui/seeded_data/x0_feasible_region_s2.xlsx +0 -0
  19. pinf-0.1.0/src/pinf/gui/seeded_data/x0_feasible_region_s2_m2.xlsx +0 -0
  20. pinf-0.1.0/src/pinf/model_construction.py +269 -0
  21. pinf-0.1.0/src/pinf/rules/__init__.py +1 -0
  22. pinf-0.1.0/src/pinf/rules/acceptability.py +177 -0
  23. pinf-0.1.0/src/pinf/rules/auxiliary_constraints.py +78 -0
  24. pinf-0.1.0/src/pinf/rules/confidence_regions.py +290 -0
  25. pinf-0.1.0/src/pinf/rules/functional_structure.py +157 -0
  26. pinf-0.1.0/src/pinf/utils/__init__.py +1 -0
  27. pinf-0.1.0/src/pinf/utils/cutoff_calculation.py +75 -0
  28. pinf-0.1.0/src/pinf/utils/functional_properties_validation.py +45 -0
  29. pinf-0.1.0/src/pinf/utils/model_construction_inputs.py +181 -0
  30. pinf-0.1.0/src/pinf/utils/solver_config.py +105 -0
  31. pinf-0.1.0/src/pinf.egg-info/PKG-INFO +418 -0
  32. pinf-0.1.0/src/pinf.egg-info/SOURCES.txt +46 -0
  33. pinf-0.1.0/src/pinf.egg-info/dependency_links.txt +1 -0
  34. pinf-0.1.0/src/pinf.egg-info/entry_points.txt +2 -0
  35. pinf-0.1.0/src/pinf.egg-info/requires.txt +22 -0
  36. pinf-0.1.0/src/pinf.egg-info/top_level.txt +1 -0
  37. pinf-0.1.0/tests/test_acceptability_screening.py +108 -0
  38. pinf-0.1.0/tests/test_cutoff_calculation.py +26 -0
  39. pinf-0.1.0/tests/test_execution_engine.py +38 -0
  40. pinf-0.1.0/tests/test_functional_structure.py +123 -0
  41. pinf-0.1.0/tests/test_gui_helpers.py +97 -0
  42. pinf-0.1.0/tests/test_gui_launcher.py +45 -0
  43. pinf-0.1.0/tests/test_input_validation.py +122 -0
  44. pinf-0.1.0/tests/test_intervals.py +116 -0
  45. pinf-0.1.0/tests/test_model_construction.py +100 -0
  46. pinf-0.1.0/tests/test_package.py +7 -0
  47. pinf-0.1.0/tests/test_pixelization.py +101 -0
  48. pinf-0.1.0/tests/test_solver_config.py +102 -0
pinf-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jinbo Zhao and David J. Eckman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pinf-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,418 @@
1
+ Metadata-Version: 2.4
2
+ Name: pinf
3
+ Version: 0.1.0
4
+ Summary: Plausible inference for simulation experiments: screening, plausible intervals and pixelization, built on Pyomo.
5
+ Author: Jinbo Zhao, David J. Eckman
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Jinbo-Zhao/pinf
8
+ Project-URL: Documentation, https://pinf.readthedocs.io/en/latest/
9
+ Project-URL: Repository, https://github.com/Jinbo-Zhao/pinf
10
+ Project-URL: Issues, https://github.com/Jinbo-Zhao/pinf/issues
11
+ Keywords: optimization,pyomo,plausible inference,simulation,statistical inference
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: numpy>=1.22
26
+ Requires-Dist: pandas>=1.5
27
+ Requires-Dist: pyomo>=6.10.1
28
+ Requires-Dist: gurobipy>=10.0
29
+ Requires-Dist: pyscipopt>=5.0
30
+ Requires-Dist: scipy>=1.9
31
+ Provides-Extra: gui
32
+ Requires-Dist: matplotlib>=3.6; extra == "gui"
33
+ Requires-Dist: streamlit>=1.28; extra == "gui"
34
+ Requires-Dist: openpyxl>=3.1; extra == "gui"
35
+ Provides-Extra: dev
36
+ Requires-Dist: pinf[gui]; extra == "dev"
37
+ Requires-Dist: pytest>=7.0; extra == "dev"
38
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
39
+ Provides-Extra: docs
40
+ Requires-Dist: sphinx>=7.2; extra == "docs"
41
+ Requires-Dist: sphinx-rtd-theme>=2.0; extra == "docs"
42
+ Requires-Dist: sphinx-autoapi>=3.0; extra == "docs"
43
+ Requires-Dist: myst-nb>=1.0; extra == "docs"
44
+ Dynamic: license-file
45
+
46
+ # Plausible Inference
47
+
48
+ [![Documentation Status](https://readthedocs.org/projects/pinf/badge/?version=latest)](https://pinf.readthedocs.io/en/latest/)
49
+
50
+ 📖 **Documentation:** <https://pinf.readthedocs.io>
51
+
52
+ <!-- start: intro -->
53
+ This repository contains code for **plausible inference** methods (Zhao et al. 2025) for analyzing the outputs of simulation experiments. The methods involve optimization subroutines built on [Pyomo](https://www.pyomo.org/).
54
+
55
+ Given a set of simulated solutions, estimates of their objective values—provided as summary statistics (e.g., sample means and sample variances) or confidence regions—and assumptions about the structure of the underlying objective function (e.g., convexity, Lipschitz continuity), this package performs inference tasks including:
56
+
57
+ - **Screening:** Perform statistical inference or hypothesis testing on the acceptability (e.g., optimality) of a candidate solution `x_0`.
58
+ - **Plausible intervals:** Construct confidence intervals or regions for the objective value(s) at a given solution `x_0`, or confidence bands for the objective function over the feasible region.
59
+ - **Pixelization:** Construct confidence regions for the set of acceptable solutions in decision (input) space, or for its image in objective (output) space.
60
+ <!-- end: intro -->
61
+
62
+ ---
63
+
64
+ ## Installation
65
+ <!-- start: installation -->
66
+
67
+ Requires Python ≥ 3.10.
68
+
69
+ ### Using the package
70
+
71
+ Install the package from PyPI:
72
+
73
+ ```bash
74
+ pip install pinf
75
+ ```
76
+
77
+ This also installs the Python interfaces of the Gurobi and SCIP solvers (see
78
+ the Solvers section). The package is imported as `pinf`.
79
+
80
+ To also install the Streamlit GUI (launched with `pinf-gui`, see the Streamlit
81
+ GUI section):
82
+
83
+ ```bash
84
+ pip install "pinf[gui]"
85
+ ```
86
+
87
+ ### Working from a clone
88
+
89
+ The tests, the demo notebooks and the documentation sources live in this
90
+ repository but are not part of the published package. To use them, clone the
91
+ repository and install it in editable mode from the repository root, inside the
92
+ Python environment you will use (for example after `conda activate <env>`):
93
+
94
+ ```bash
95
+ git clone https://github.com/Jinbo-Zhao/pinf.git
96
+ cd pinf
97
+ pip install -e ".[gui]" # Streamlit GUI (pinf-gui) and the demo notebooks
98
+ pip install -e ".[dev]" # tests and linting (pytest, ruff); includes gui
99
+ pip install -e ".[docs]" # build the documentation locally
100
+ ```
101
+
102
+ ### Available extras
103
+
104
+ | Extra | Adds | Needed for |
105
+ |---|---|---|
106
+ | *(none)* `pip install pinf` | NumPy, pandas, SciPy, Pyomo, gurobipy, PySCIPOpt | Building and solving models |
107
+ | `gui` | Streamlit, Matplotlib, openpyxl | The Streamlit GUI (`pinf-gui`) and the demo notebooks |
108
+ | `dev` | pytest, ruff, and the `gui` extra | Tests and linting (from a clone) |
109
+ | `docs` | Sphinx, MyST, Read the Docs theme, sphinx-autoapi | Building the documentation (from a clone) |
110
+
111
+ Every extra already includes the core package. Combine extras in one command,
112
+ for example `pip install -e ".[gui,dev]"`.
113
+ <!-- end: installation -->
114
+
115
+ ---
116
+
117
+ ## Main Elements
118
+ <!-- start: concepts -->
119
+
120
+ | Concept | Meaning |
121
+ |---|---|
122
+ | **Experimental set** | `exp_set`, shape `(k, s)`: `k` simulated solutions in `s`-dim decision space. |
123
+ | **Plausible objective values** | `m[i, d]`: an intermediate modeling quantity representing objective `d` at solution `i`. Index `0` corresponds to the candidate solution `x_0`; indices `1..k` correspond to the simulated solutions. |
124
+ | **Functional properties** | Structural assumptions on the objective: `convexity`, `concavity`, `Lipschitz_continuity`, `directional_Lipschitz_continuity` (one set per objective). |
125
+ | **Acceptability** | What makes `x_0` "acceptable" (see below). Smaller values are assumed to be preferred for every objective. Defined in terms of `m[0, :]`. |
126
+ | **Confidence region** | A region that constrains the objective values at the simulated solutions, specified directly through bounds on each objective or constraints. |
127
+ | **Discrepancy type** | Specifies how to construct a confidence region from summary statistics. Only one of a discrepancy type or an explicitly specified confidence region is required. |
128
+
129
+ ### Inference Types
130
+
131
+ All inference types use statistics computed from the simulation outputs at the simulated solutions, or a confidence region for their objective values.
132
+
133
+ - **`screening`**: Test whether a given solution `x_0` is one of the acceptable solutions.
134
+ - **`upper_plausible_interval`**: Construct an upper confidence bound on a selected objective value at a given solution `x_0`.
135
+ - **`lower_plausible_interval`**: Construct a lower confidence bound on a selected objective value at a given solution `x_0`.
136
+ - **`input_pixelization`**: Test whether a given region in solution (input) space intersects an implicitly defined confidence region for acceptable solutions.
137
+ - **`output_pixelization`**: Test whether a given region in objective (output) space intersects an implicitly defined confidence region for the image of acceptable solutions under the objective function.
138
+
139
+ Inference procedures based on the same simulation statistics or confidence region provide a **uniform confidence guarantee**: with probability at least `1 - alpha`, none of the resulting conclusions makes a Type I error. Here, `1 - alpha` is the confidence level of the provided confidence region, or the confidence level specified when selecting a discrepancy type.
140
+
141
+ Plausible intervals are computed one objective at a time: pass `interval_objective_index` (1-based, default `1`) to `model_construction` to choose which objective is bounded.
142
+
143
+ ### Acceptabilities
144
+
145
+ Smaller values are assumed to be preferred for every objective. Objectives for which larger values are preferred can be multiplied by `-1` to follow this convention.
146
+
147
+ | Name | Definition | Parameters |
148
+ |---|---|---|
149
+ | `single-objective-optimality` | The solution achieves the smallest objective value over the feasible region. | — |
150
+ | `delta-optimality` | The solution's objective value is within `delta` of the smallest objective value over the feasible region. | `{'delta': ≥0}` |
151
+ | `feasibility` | The solution's objective value is at or below a specified `threshold`. | `{'threshold': c}` (scalar, or one value per objective) |
152
+ | `closeness-to-target` | The solution's objective value differs from a specified `threshold` by at most `delta`. | `{'threshold': c, 'delta': ≥0}` (each a scalar, or one value per objective) |
153
+ | `Pareto-optimality` | No other feasible solution is at least as good in every objective and strictly better in at least one objective. | — |
154
+
155
+ `single-objective-optimality` and `delta-optimality` apply to a single objective, and `Pareto-optimality` applies to multiple objectives. `feasibility` and `closeness-to-target` apply to any number of objectives, imposing the condition on each objective separately. Parameters are passed via `acceptability_parameters`.
156
+
157
+ ### Discrepancy Types
158
+
159
+ A discrepancy is a distance measure that quantifies the disagreement between objective values and simulation observations.
160
+
161
+ For each objective `d`, let
162
+
163
+ $$
164
+ z_{i,d} = \frac{m[i,d] - \bar{Y}_{i,d}}{S_{i,d}/\sqrt{n_{i,d}}},
165
+ $$
166
+
167
+ where $\bar{Y}_{i,d}$, $S_{i,d}^2$, and $n_{i,d}$ are the sample mean, sample variance, and sample size at simulated solution `i`.
168
+
169
+ - **`norm_1`**: Sum the absolute standardized differences:
170
+
171
+ $$
172
+ D_d = \sum_{i=1}^{k} |z_{i,d}|.
173
+ $$
174
+
175
+ - **`norm_2`**: Sum the squared standardized differences:
176
+
177
+ $$
178
+ D_d = \sum_{i=1}^{k} z_{i,d}^{2}.
179
+ $$
180
+
181
+ - **`norm_infinite`**: Take the largest absolute standardized difference:
182
+
183
+ $$
184
+ D_d = \max_{i=1,\ldots,k} |z_{i,d}|.
185
+ $$
186
+
187
+ - **`CRN`**: Use a covariance-adjusted squared distance to account for correlations between simulation outputs at different solutions, such as those induced by common random numbers:
188
+
189
+ $$
190
+ D_d = n_d(\mathbf{m}_d-\bar{\mathbf{Y}}_d)^\top
191
+ \widehat{\Sigma}_d^{-1}
192
+ (\mathbf{m}_d-\bar{\mathbf{Y}}_d).
193
+ $$
194
+
195
+ Here, $\mathbf{m}_d=(m[1,d],\ldots,m[k,d])^\top$, $\bar{\mathbf{Y}}_d$ is the vector of sample means, $\widehat{\Sigma}_d$ is the sample covariance matrix of simulation outputs, and $n_d$ is the common sample size across simulated solutions.
196
+
197
+ - **`confidence_region`**: Directly use a precomputed confidence region specified through `lower_confidence_bounds` and `upper_confidence_bounds`.
198
+
199
+ The three norm-based types assume independent sampling across simulated solutions and use `sample_mean`, `sample_var`, and `sample_size`. For `CRN`, `sample_var` provides a sample covariance matrix across simulated solutions for each objective.
200
+
201
+ For statistics-based types, the package constructs a confidence region by bounding each discrepancy using a cutoff determined by `confidence_level`, with a Bonferroni correction across objectives. For each objective `d`, the resulting region for $(m[1,d], \ldots, m[k,d])$ is a polyhedron for `norm_infinite` (a hyperrectangle) and `norm_1` (a cross-polytope), an axis-aligned ellipsoid for `norm_2`, and an ellipsoid whose axes follow $\widehat{\Sigma}_d$ for `CRN`; with multiple objectives, the overall region is the Cartesian product of these per-objective regions. For `confidence_region`, the region is the hyperrectangle given by the bounds, which should jointly cover the objective values across all simulated solutions and objectives at the intended confidence level.
202
+ <!-- end: concepts -->
203
+
204
+ ---
205
+
206
+ ## Quick Start
207
+ <!-- start: quickstart -->
208
+
209
+ **Before you run it:** install the package:
210
+
211
+ ```bash
212
+ pip install pinf
213
+ ```
214
+
215
+ ```python
216
+ import numpy as np
217
+ from pinf.model_construction import model_construction
218
+ from pinf.utils.solver_config import get_plausibility_solver
219
+ from pinf.execution_engine import ExecutionConfig, run_execution_engine
220
+
221
+ # Two simulated solutions in 2-D, single objective, with explicit confidence bounds.
222
+ exp_set = np.array([[0.0, 0.0], [1.0, 1.0]])
223
+ lower = np.array([[1.0], [2.0]])
224
+ upper = np.array([[2.0], [3.0]])
225
+
226
+ # Build a screening model: is x_0 a near-optimal (within 0.5) point for some convex
227
+ # objective consistent with the data?
228
+ model = model_construction(
229
+ exp_set,
230
+ num_objectives=1,
231
+ inference_type="screening",
232
+ functional_properties_list=[["convexity"]],
233
+ acceptability="delta-optimality",
234
+ acceptability_parameters={"delta": 0.5},
235
+ discrepancy_type="confidence_region",
236
+ upper_confidence_bounds=upper,
237
+ lower_confidence_bounds=lower,
238
+ feasibility_check_solver=None, # skip the structural feasibility pre-check
239
+ )
240
+
241
+ solver = get_plausibility_solver("gurobi")
242
+ candidates = np.array([[5.0, 5.0]]) # one candidate x_0, shape (n, s)
243
+ results = run_execution_engine(ExecutionConfig(inference_type="screening"), model, solver, candidates)
244
+ print(results) # DataFrame: idx, solve_status='completed', result='returned'/'screened_out'
245
+ ```
246
+
247
+ Using statistics instead of explicit bounds:
248
+
249
+ ```python
250
+ model = model_construction(
251
+ exp_set,
252
+ num_objectives=1,
253
+ inference_type="screening",
254
+ functional_properties_list=[["convexity"]],
255
+ acceptability="single-objective-optimality",
256
+ discrepancy_type="norm_infinite",
257
+ sample_mean=np.array([[1.0], [2.0]]),
258
+ sample_var=np.array([[0.5], [0.5]]), # must be finite and > 0
259
+ sample_size=100.0,
260
+ confidence_level=0.95, # must be in (0, 1)
261
+ feasibility_check_solver=None,
262
+ )
263
+ ```
264
+
265
+ Once you have a model, use `run_execution_engine` to solve the inference over your
266
+ candidate points. It returns one `pandas.DataFrame` with a row per point:
267
+
268
+ ```python
269
+ from pinf.execution_engine import ExecutionConfig, run_execution_engine
270
+
271
+ results = run_execution_engine(
272
+ ExecutionConfig(inference_type="screening"),
273
+ model,
274
+ solver,
275
+ candidates,
276
+ )
277
+ ```
278
+ <!-- end: quickstart -->
279
+
280
+ ---
281
+
282
+ ## Solvers
283
+ <!-- start: solvers -->
284
+
285
+ Plausible inference must distinguish **infeasible** from **unbounded**, which solver
286
+ presolve can otherwise hide (`INF_OR_UNBD`). Always create the solver via
287
+ `get_plausibility_solver(name)`, which sets the right options:
288
+
289
+ - **Gurobi** — `DualReductions = 0`
290
+ - **SCIP** — `misc/allowstrongdualreds = False`, `misc/allowweakdualreds = False`
291
+
292
+ Models built with `norm_2` or `CRN` contain quadratic constraints; both solvers
293
+ handle them.
294
+
295
+ ### Gurobi
296
+
297
+ Solver names: `gurobi`, `gurobi_direct`.
298
+
299
+ ```bash
300
+ pip install pinf # includes gurobipy
301
+ ```
302
+
303
+ The pip-installed `gurobipy` includes a size-limited license that is enough for
304
+ small examples. Larger models need a full Gurobi license (free for academic use);
305
+ see the [Gurobi license documentation](https://support.gurobi.com/hc/en-us/articles/12684663118993-How-do-I-obtain-a-Gurobi-license).
306
+
307
+ ### SCIP
308
+
309
+ SCIP is open source but can be reached through two Pyomo interfaces, which are
310
+ installed differently:
311
+
312
+ | Solver name | What it uses | How to install |
313
+ |---|---|---|
314
+ | `scip_direct` | PySCIPOpt (Python bindings that bundle the SCIP library) | included in `pip install pinf` |
315
+ | `scip` | the `scip` command-line executable | `conda install -c conda-forge scip`, or download an installer from [scipopt.org](https://www.scipopt.org/) |
316
+
317
+ `pip install pyscipopt` does **not** provide the `scip` executable, so with a
318
+ pip-only setup use `scip_direct`. To use `scip`, check that the executable is on
319
+ `PATH` with `scip --version`. `scip_direct` requires Pyomo 6.10.1 or
320
+ later, which `pip install pinf` installs.
321
+
322
+ ### Checking a solver
323
+
324
+ ```python
325
+ from pinf.utils.solver_config import get_plausibility_solver
326
+
327
+ solver = get_plausibility_solver("scip_direct") # or "gurobi", "scip", ...
328
+ print(solver.available(exception_flag=False)) # True when Pyomo can use it
329
+ ```
330
+
331
+ ### Structural feasibility check
332
+
333
+ `model_construction` first checks that the functional-property and
334
+ confidence-region constraints are feasible. Choose the solver with
335
+ `feasibility_check_solver` (`gurobi`, `gurobi_direct`, `scip` or `scip_direct`;
336
+ default `scip_direct`), or pass `None` to skip the check.
337
+ <!-- end: solvers -->
338
+
339
+ ---
340
+
341
+ ## Streamlit GUI
342
+ <!-- start: gui -->
343
+
344
+ The GUI ships with the package. Install it with the GUI extra:
345
+
346
+ ```bash
347
+ pip install "pinf[gui]"
348
+ ```
349
+
350
+ Then start it from the directory where you want results to be saved:
351
+
352
+ ```bash
353
+ pinf-gui
354
+ ```
355
+
356
+ Streamlit prints a local URL (usually <http://localhost:8501>) and opens it in
357
+ your browser. Stop the app with Ctrl+C in the terminal. Results are written to
358
+ `inference_results/` under the launch directory. Options after `pinf-gui` are
359
+ passed to `streamlit run`, for example `pinf-gui --server.port 8600`.
360
+
361
+ The GUI guides the user through problem setup, acceptability + threshold inputs, simulation
362
+ upload (statistics or bounds templates), procedure-specific inputs (candidate points or
363
+ pixel grids), and runs the inference with downloadable results.
364
+ <!-- end: gui -->
365
+
366
+ ---
367
+
368
+ ## Project Layout
369
+
370
+ ```
371
+ src/pinf/
372
+ ├── model_construction.py # build the Pyomo model (entry point)
373
+ ├── execution_engine.py # batch-solve the optimization problems (run_execution_engine)
374
+ ├── rules/
375
+ │ ├── functional_structure.py # convexity / concavity / linearity / Lipschitz
376
+ │ ├── acceptability.py # acceptability constraints
377
+ │ ├── confidence_regions.py # discrepancy measures + cutoffs
378
+ │ └── auxiliary_constraints.py # abs/max linearization helpers
379
+ ├── utils/
380
+ │ ├── cutoff_calculation.py # Monte-Carlo / closed-form discrepancy cutoffs
381
+ │ ├── model_construction_inputs.py # input validation
382
+ │ ├── functional_properties_validation.py # property-parameter validation
383
+ │ └── solver_config.py # solver factory + time limits
384
+ └── gui/
385
+ ├── app.py # Streamlit app
386
+ ├── helpers.py # parsing, templates, argument builders
387
+ ├── launcher.py # `pinf-gui` entry point
388
+ └── seeded_data/ # example CSV/XLSX inputs
389
+ ```
390
+
391
+ ---
392
+
393
+ ## License
394
+
395
+ This project is licensed under the MIT License. See [`LICENSE`](https://github.com/Jinbo-Zhao/pinf/blob/main/LICENSE) for details.
396
+
397
+ Copyright (c) 2026 Jinbo Zhao and David J. Eckman.
398
+ ## Testing
399
+ <!-- start: testing -->
400
+
401
+ ```bash
402
+ pip install -e ".[dev]"
403
+ pytest
404
+ ```
405
+
406
+ Solve tests need Gurobi and SCIP available through Pyomo. The package
407
+ installs `gurobipy` and PySCIPOpt (for `scip_direct`). Tests of the `scip`
408
+ interface also need the SCIP executable on `PATH`
409
+ (e.g. `conda install -c conda-forge scip`).
410
+ <!-- end: testing -->
411
+
412
+ ---
413
+
414
+ ## References
415
+ <!-- start: references -->
416
+
417
+ - Zhao, J., G. Keslin, D. J. Eckman, and B. L. Nelson. "[Methods of Plausible Inference: The Definitive Cookbook](https://www.informs-sim.org/wsc25papers/inv171.pdf)". Proceedings of the 2025 Winter Simulation Conference. 2025. 88–102.
418
+ <!-- end: references -->