Pyomo integration for paramclass.
Project description
paramclass-pyomo
paramclass-pyomo adapts Pyomo's imperative modeling API to declarative,
class-body model definitions.
It is built on top of paramclass and
lets you describe Pyomo components as class attributes, then materialize them
onto a pyomo.environ.Block or ConcreteModel.
import pyomo.environ as pyo
from paramclass_pyomo import AbstractBlock
class ToyBlock(AbstractBlock):
x = pyo.Var(initialize=3)
c = pyo.Constraint(rule=lambda m: m.x >= 1)
e = pyo.Expression(rule=lambda m: m.x + 1)
o = pyo.Objective(rule=lambda m: m.e)
model = pyo.ConcreteModel()
ToyBlock().build(model)
assert pyo.value(model.x) == 3
assert str(model.c.expr) == "1 <= x"
The goal is to make reusable Pyomo model pieces easier to package, override, compose, test, lint, and statically analyze.
Project Timeline
paramclass-pyomo was developed during 2023-2024 and has been used in
production workflows since 2023. Public packaging was added in 2025, and public
documentation was added in 2026 to make the project easier to evaluate, install,
and reuse outside its original environment.
Install
pip install paramclass-pyomo
For local development alongside paramclass:
uv sync --extra dev
uv run --extra dev pytest
The local UV configuration uses ../paramclass as an editable dependency.
Why
Pyomo is powerful, but reusable model structure often ends up split across factory functions, ad hoc builders, and imperative component assignment:
model = pyo.ConcreteModel()
model.capacity = pyo.Param(initialize=100, mutable=True)
model.used = pyo.Var(bounds=(0, None))
model.limit = pyo.Constraint(rule=lambda m: m.used <= m.capacity)
That style is natural for Pyomo, but it gives developer tooling less structure to inspect. Class-based definitions provide a stable surface for code review, linting, static analysis, generated documentation, and model composition.
AbstractBlock keeps Pyomo's component model, while giving each reusable block a
compact Python class definition:
class CapacityBlock(AbstractBlock):
capacity = pyo.Param(initialize=100, mutable=True)
used = pyo.Var(bounds=(0, None))
limit = pyo.Constraint(rule=lambda m: m.used <= m.capacity)
Then build it onto a model:
model = pyo.ConcreteModel()
CapacityBlock().build(model)
This keeps the imperative construction where Pyomo expects it, while moving the authoring experience toward a declarative design.
Examples
Standard Pyomo Keyword Style
Normal Pyomo keyword construction is supported. Use rule= for constraints,
expressions, and objectives, and initialize= for parameters and variables.
class ObjectiveBlock(AbstractBlock):
p = pyo.Param(initialize=7, mutable=True)
x = pyo.Var(initialize=lambda m: pyo.value(m.p) + 1)
objective = pyo.Objective(rule=lambda m: m.x)
Shorthand Rule Calls
paramclass-pyomo also supports a shorthand callable style for rules:
class ConstraintBlock(AbstractBlock):
x = pyo.Var(initialize=3)
c = pyo.Constraint()(lambda m: m.x >= 1)
This is optional. The standard Pyomo rule= form is usually clearer for public
examples and team code.
Nested Blocks
AbstractBlock instances can be assigned as attributes of other
AbstractBlocks. Nested blocks are finalized onto the parent block during
construction.
class Inner(AbstractBlock):
x = pyo.Var(initialize=1)
class Outer(AbstractBlock):
inner = Inner()
cap = pyo.Constraint(rule=lambda m: m.inner.x <= 10)
model = pyo.ConcreteModel()
Outer().build(model)
Indexed Blocks
Pass indexing arguments to the block constructor when defining nested blocks:
class Unit(AbstractBlock):
x = pyo.Var(initialize=1)
class System(AbstractBlock):
units = Unit(["a", "b", "c"])
When a block is indexed, component construction is applied across each block data object.
How It Works
AbstractBlock extends ParamClass and redirects public attribute assignment to
the underlying Pyomo block. During build(model), deferred class-body
definitions are evaluated and attached to the target model or block.
This lets a Pyomo block definition look declarative to developers and tooling, while still executing through Pyomo's normal component lifecycle.
Pyomo components that already belong to another block are wrapped with a small proxy so they can still be referenced safely from generated components.
Current Limitations
This project intentionally stays close to Pyomo's component model. If a Pyomo
constructor requires keyword arguments such as rule= or initialize=, prefer
using those explicit keywords in public code.
As with paramclass, Python boolean operators such as and, or, and not
are not deferred by the tracing layer.
Testing
uv run --extra dev pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paramclass_pyomo-1.1.1.tar.gz.
File metadata
- Download URL: paramclass_pyomo-1.1.1.tar.gz
- Upload date:
- Size: 8.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fac82f7bb02f414686ae5ed6887d59b461048e950152683fe01e9294e393de9c
|
|
| MD5 |
ed7918cf1cc0fab7240d02776dffd0db
|
|
| BLAKE2b-256 |
6d3a8427ed887ac6d78348468bba7692e33dcbd463a2df4a831267ca90a442c0
|
File details
Details for the file paramclass_pyomo-1.1.1-py3-none-any.whl.
File metadata
- Download URL: paramclass_pyomo-1.1.1-py3-none-any.whl
- Upload date:
- Size: 7.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1162c6c058fa862aabc785ea13527e8b486b89b510ae7e82dcd043c3ff644d49
|
|
| MD5 |
d51bcd18c2de594338ea489be4aa6a9c
|
|
| BLAKE2b-256 |
ae29a655df684d8a779764aa76eff51bf5259670f718b69d38c841e4c963fc2f
|