From c60cf5edd4c50caa07d24bea0c8ba7d9c390e3f2 Mon Sep 17 00:00:00 2001 From: "David E. Bernal Neira" Date: Wed, 4 Feb 2026 17:48:19 -0500 Subject: [PATCH] Add Pyomo optional dependencies and module structure This PR adds the foundation for Pyomo integration: pyproject.toml changes: - Add [optimization] extra with pyomo>=6.7.0 and idaes-pse>=2.9.0 - These are optional dependencies, scipy-based code works without them Module structure: - lyopronto/pyomo_models/__init__.py: Placeholder with documentation - tests/test_pyomo_models/__init__.py: Test directory placeholder Installation: pip install .[optimization] # For Pyomo support pip install . # Standard scipy-only installation This enables users to opt-in to Pyomo optimization without affecting existing scipy-based workflows. --- lyopronto/pyomo_models/__init__.py | 49 ++++++++++++++++++ pyproject.toml | 79 ++++++++++++++++++++++++++++- tests/test_pyomo_models/__init__.py | 2 + 3 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 lyopronto/pyomo_models/__init__.py create mode 100644 tests/test_pyomo_models/__init__.py diff --git a/lyopronto/pyomo_models/__init__.py b/lyopronto/pyomo_models/__init__.py new file mode 100644 index 0000000..39ca25f --- /dev/null +++ b/lyopronto/pyomo_models/__init__.py @@ -0,0 +1,49 @@ +# Copyright 2019-2025, Gayathri Shivkumar, Petr S. Kazarin, Alina A. Alexeenko +# Maintained by Isaac S. Wheeler +# +# This file is part of LyoPRONTO. +# LyoPRONTO is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +Pyomo-based optimization models for lyophilization process. + +This module provides Pyomo-based formulations for lyophilization optimization, +complementing the existing scipy-based optimizers. The Pyomo models offer: + +- Mathematical programming formulations with explicit constraints +- Support for IPOPT and other NLP solvers +- Multi-period trajectory optimization +- Orthogonal collocation discretization + +Usage: + # Install optimization dependencies first: + # pip install .[optimization] + + from lyopronto.pyomo_models import optimize_Tsh_pyomo + + result = optimize_Tsh_pyomo(vial, product, ht, Pchamber, Tshelf, dt, eq_cap, nVial) + +The optimizers maintain API compatibility with scipy-based versions: +- optimize_Tsh_pyomo: Optimize shelf temperature trajectory +- optimize_Pch_pyomo: Optimize chamber pressure trajectory +- optimize_Pch_Tsh_pyomo: Optimize both pressure and temperature + +Note: Requires IPOPT solver. Install via: idaes get-extensions --extra petsc +""" + +# Placeholder - actual implementations will be added in subsequent PRs +__all__ = [] + +# Version will be set when implementations are added +__version__ = "0.1.0-dev" diff --git a/pyproject.toml b/pyproject.toml index b9428a7..760a2a6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,10 @@ classifiers = [ ] [project.optional-dependencies] +optimization = [ + "pyomo>=6.7.0", + "idaes-pse>=2.9.0", +] dev = [ "pytest>=7.4.0", "pytest-mock>=3", @@ -58,7 +62,9 @@ docs = [ "mike>=2.1", "mkdocs-ipynb>=0.1.1", ] - +all = [ + "lyopronto[optimization,dev,docs]", +] [project.urls] Homepage = "http://lyopronto.geddes.rcac.purdue.edu" @@ -88,4 +94,75 @@ markers = [ "fast: Quick tests that run in under 1 second", "notebook: Tests that execute Jupyter notebooks for documentation", "main: Tests that cover functionality previously included in main.py", + "pyomo: Tests requiring Pyomo and IPOPT solver (deselect with '-m not pyomo')", + "serial: Tests that must run serially (not in parallel)", +] + +[tool.mypy] +python_version = "3.8" +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = false +ignore_missing_imports = true +# Exclude pyomo_models from type checking - Pyomo uses dynamic attribute +# assignment (model.Var = pyo.Var(...)) which generates many false-positive +# mypy errors. The code is tested via pytest instead. +exclude = [ + "lyopronto/pyomo_models/", +] + +[tool.ruff] +# Target Python 3.8+ (matches project.requires-python) +target-version = "py38" +line-length = 88 # Black-compatible +src = ["lyopronto", "tests", "benchmarks"] + +[tool.ruff.lint] +# Enable recommended rules + some extras +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # Pyflakes + "I", # isort (import sorting) + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "UP", # pyupgrade + "SIM", # flake8-simplify +] +ignore = [ + "E501", # Line too long (handled by formatter) + "B008", # Do not perform function calls in argument defaults + "SIM108", # Use ternary operator (sometimes less readable) ] + +# Allow autofix for all enabled rules +fixable = ["ALL"] +unfixable = [] + +[tool.ruff.lint.per-file-ignores] +# Tests can use assert and have longer lines +"tests/**/*.py" = ["S101", "E501"] +# Pyomo test files have conditional imports at module level (intentional pattern) +"tests/test_pyomo_models/*.py" = ["E402", "E722", "F401"] +# Pyomo models use closures in loops for rule functions (Pyomo pattern) +"lyopronto/pyomo_models/*.py" = ["B023", "B007", "E722", "SIM102", "F811"] +# Legacy scipy optimizers use closures in loops (legacy pattern) +"lyopronto/opt_*.py" = ["B023"] +# Package __init__ re-exports modules for public API +"lyopronto/__init__.py" = ["F401"] +# Benchmarks may have more complex imports +"benchmarks/**/*.py" = ["E501"] +# Legacy examples may have style issues +"examples/legacy/**/*.py" = ["ALL"] +# Notebooks have different import patterns +"**/*.ipynb" = ["E402", "B007"] +# Test design space has complex warning handling +"tests/test_design_space.py" = ["SIM117"] + +[tool.ruff.format] +# Use double quotes (Black-compatible) +quote-style = "double" +# Indent with spaces +indent-style = "space" +# Unix line endings +line-ending = "lf" diff --git a/tests/test_pyomo_models/__init__.py b/tests/test_pyomo_models/__init__.py new file mode 100644 index 0000000..abbbe44 --- /dev/null +++ b/tests/test_pyomo_models/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2019-2025, SECQUOIA +# Tests for Pyomo-based optimization models.