Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions lyopronto/pyomo_models/__init__.py
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

"""
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"
79 changes: 78 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
Expand Down Expand Up @@ -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"
2 changes: 2 additions & 0 deletions tests/test_pyomo_models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copyright 2019-2025, SECQUOIA
# Tests for Pyomo-based optimization models.
Loading