Skip to main content

drto

PyPI Python versions CI Docs License

DRTO is a unified framework for dynamic real-time optimization built on Pyomo.

Status

Alpha. The registry (drto.info), the declaration surface, objective assembly, the control-profile application, and the infinite-horizon terminal segment (features 001-004 and 017) are implemented and tested; the mode transforms, initializers, and closed-loop frameworks follow. The feature statuses live in features/README.md, and DESIGN.md remains the design record.

Install

pip install drto

The pounce solver and pyomo-pounce are needed for full functionality (sensitivity updates, the advanced-step frameworks); any NLP solver runs the open-loop modes.

Spec-driven development

drto is built spec-first: every feature is specified under features/ before it is implemented, as a short doc with a status, a user-story description, a benefit hypothesis, and acceptance criteria that drive the tests. See features/README.md. A feature request may be made by opening a pull request that adds a feature file under features/ in the template format.

Modes

drto runs one declared model in any of six modes, the 2x3 grid of {steady-state, dynamic} by {simulation, optimization, estimation}. You write the model once; the mode fixes what is free and what the objective is.

Simulation Optimization Estimation
Steady-state solve the model at equilibrium economic RTO data reconciliation
Dynamic integrate the model forward NMPC / D-RTO moving horizon estimation

Down the columns: simulation frees nothing and solves the model as given; optimization frees the controls and adds a cost; estimation frees the states and fits them to measurements. Across the rows: the steady-state modes solve at a single equilibrium point, the dynamic modes keep the time horizon. A dynamic model is collapsed to that equilibrium, and a model authored directly as steady-state, with no time or dynamics, runs in the steady-state modes as it stands, so a user can define the model either way and still use it across the modes. The optimization and estimation columns are duals (NMPC with MHE, RTO with reconciliation), so one declaration surface serves both.

The near-term focus is the optimization column: dynamic NMPC/D-RTO, whose ideal, nonideal, and advanced-step execution variants are the headline, plus steady-state RTO. Estimation is the planned follow-on.

Transformations

The six modes above are each a single solve exposed as a Pyomo transformation under the drto. namespace, alongside the lower-level transformations they compose. You build one declared model and apply the transformation you want, the same way you apply any Pyomo transformation.

Transformation Registered as
Steady-state simulation drto.steady_state_simulation
Steady-state optimization drto.steady_state_optimization
Steady-state estimation drto.steady_state_estimation
Dynamic simulation drto.dynamic_simulation
Dynamic optimization drto.dynamic_optimization
Dynamic estimation drto.dynamic_estimation
Objective assembly drto.build_objective
Steady-state reduction drto.dynamic_to_steady_state
Infinite-horizon terminal segment drto.infinite_horizon
Control profile application drto.parameterize

Closed-loop frameworks

Separately from the modes come the closed-loop frameworks: the dynamic optimization loop in ideal, nonideal, and advanced-step forms (drafted as features 014-016), and the estimation loops, specced later.

Ideal Nonideal Advanced Step
Optimization ideal_nmpc nonideal_nmpc asnmpc
Estimation MHE asMHE

The advanced-step column, asnmpc and asMHE, is built on drto.advanced_step_controller: it solves the horizon at a predicted state and then corrects to the actual state with a fast pounce sensitivity update rather than a re-solve.

Initialization routines

A good initial guess is often the difference between an IPOPT solve that converges and one that stalls, so drto provides named initializers rather than leaving each user to hand-roll one. These are plain functions, not transformations: they leave the model structure alone and only populate the variable values (the initial guess), so there is no apply_to or create_using form.

Initializer What it does
initialize_steady_state Solve the steady-state form and broadcast that equilibrium across every time point: a flat starting trajectory.
cold_start_dynamic Simulate the model forward from the initial condition under nominal controls, a feasible starting trajectory for the first solve with no history.
warm_start_dynamic Shift the previous horizon's solution forward one step and fill the tail: the standard receding-horizon warm start.

warm_start_dynamic is really a loop operation that belongs with the closed-loop frameworks, listed here alongside its siblings for completeness.

Declaring an optimization or simulation problem

drto is declaration-first, and each declaration tags a Pyomo component you already wrote: a Variable, a Constraint, a Parameter, or a Set. You build your dynamic model as an ordinary Pyomo model, then point the declarations at its pieces; drto assembles the horizon problem and runs the loop. It bolts onto an existing model rather than replacing how you build one. The same functions also wrap construction (m.z = state(pyo.Var(m.t)) registers at attachment), and the constraint-role declarations double as decorators (@drto.dynamics(m, m.t)); the styles mix freely per component (feature 002 shows both in full). The pieces are the object types of a dynamic optimization or simulation problem:

DRTO object type Pyomo object type Declaration What it is
Time set Set horizon(m.t) The moving-horizon dimension. A pyomo.dae ContinuousSet, the root handle for the horizon. Dynamics are declared separately, below.
State Variable state(m.z, ...) A state variable. In a dynamic model it carries a DerivativeVar, with its dynamics declared separately below. In a steady-state model it need not have one.
Dynamics Constraint dynamics(m.ode_con) Equality ODE; one side is the state's DerivativeVar (dz/dt).
Control Variable control(m.u, ..., profile=...) A manipulated input, the decision variable. The profile flag sets its parameterization (piecewise-constant, ...) via pyomo-cvp, over the declared time set.
Tracking stage cost Constraint tracking_stage_cost(m.tracking_stage_con) Per-sample equality for the setpoint-tracking running cost; drto sums its cost var over the samples in the objective.
Economic stage cost Constraint economic_stage_cost(m.economic_stage_con) Per-sample equality for the economic running cost; its single-point steady-state form is the RTO objective.
Tracking terminal cost Constraint tracking_terminal_cost(m.tracking_terminal_con) Equality defining the terminal tracking cost; its scalar cost var goes in the objective.
Initial condition Constraint initial_condition(m.init_con) Equality anchoring the initial state; the state at t0 on one side, the feedback Param on the other.
Terminal constraint Constraint terminal_constraint(m.terminal_con) Constraint on the states at the final time; the terminal set the final state must lie in.
Steady-state target Parameter steady_state(m.z, m.z_ss) The state setpoint the tracking costs drive toward, paired with its state so the steady-state/RTO solve knows which target to populate.
Steady-state control target Parameter steady_state_control(m.u, m.u_ss) The control setpoint the tracking costs drive toward, paired with its control the same way.

Conventions drto enforces on those constraints: the cost and initial-condition constraints are equalities with the scalar the declaration is about (the cost term, or the anchored state) on one side, either orientation; a stage cost applies at every sample point except the final one, where only the terminal cost applies; a terminal constraint may reference only states at the final time, which is what separates it from a path constraint. The objective is drto's own: it sums the declared cost terms that are live in the current mode, so a mode drops a term just by leaving out its constraint.

One modeling practice worth following: leave cost variables unbounded. The defining equality already fixes each cost value (a sum of squares is nonnegative without being told), and a NonNegativeReals bound puts the optimum exactly on the bound wherever the cost vanishes, at settled samples on long horizons or through an infinite-horizon tail at equilibrium, which drags interior-point solvers (measured on the Hicks example at N = 50: 43 ipopt iterations bounded, 6 unbounded, identical solutions).

One thing you never declare, because it already lives in the model: the path constraints are the state variables' own upper and lower bounds.

The vocabulary is the optimal-control literature's own (stage cost, terminal cost, terminal constraint), so a model reads the way the theory does. The other modes reuse the same model: simulation drops the cost, and estimation swaps the initial condition for a soft arrival cost and adds the estimation pieces below.

Declaring an estimation problem

Estimation is the dual half (moving horizon estimation, the planned follow-on), and it declares its own pieces the same way. MHE fits the model to a moving window of measurements, so the free variables and the objective terms differ, but the conventions carry over: each declaration tags a Var, a Constraint, or a Param, and drto assembles the estimation objective from the live cost terms.

DRTO object type Pyomo object type Declaration What it is
Estimated parameter Variable estimated_parameter(m.theta, ...) Unknown model parameters to estimate, constant over the window. Shared with steady-state data reconciliation.
Disturbance Variable disturbance(m.w, ...) Process-noise variables (dz/dt = f + w) the estimator adjusts to fit the data, penalized by their covariance.
Measurement Parameter measurement(m.y_meas, ...) The measured values in the estimation cost residuals; a mutable Param drto refreshes each step.
Estimation stage cost Constraint estimation_stage_cost(m.est_stage_con) Equality defining the running estimation cost: measurement residual plus process-noise penalty over the window.
Estimation terminal cost Constraint estimation_terminal_cost(m.est_terminal_con) Equality for the current-time measurement residual (no process noise leads out of the last point).
Arrival cost Constraint arrival_cost(m.arrival_con) Equality for the soft prior on the window's initial state; its weight is updated by covariance propagation.

The arrival cost is the soft dual of the control side's initial condition, and the estimation stage and terminal costs are the measurement-fitting counterparts of the tracking costs.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drto-0.2.1.tar.gz (1.2 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

drto-0.2.1-py3-none-any.whl (30.6 kB view details)

Uploaded Python 3

File details

Details for the file drto-0.2.1.tar.gz.

File metadata

  • Download URL: drto-0.2.1.tar.gz
  • Upload date:
  • Size: 1.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for drto-0.2.1.tar.gz
Algorithm Hash digest
SHA256 b6ff80c9387f90a722c801d7c695ec521110d7934755f37c0a8662f36c9b9206
MD5 cbf94f1d09a9be0d92a0e8417aa74980
BLAKE2b-256 2521ef898f78a4b62f81e2090ea72023ae24cc7b9335e14cb5b4c98f0fcf9231

See more details on using hashes here.

Provenance

The following attestation bundles were made for drto-0.2.1.tar.gz:

Publisher: publish.yml on devin-griff/drto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file drto-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: drto-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 30.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for drto-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 dcf93d410f1e7894eb8f51494381db86d52198afd4a768fa2a4cda79b6254335
MD5 7695b0242318d21b42a079251d3ae777
BLAKE2b-256 73aeb1b2950c931f555c9c5f68d522daffdbad1ecb35c4c46955ec62515ca35c

See more details on using hashes here.

Provenance

The following attestation bundles were made for drto-0.2.1-py3-none-any.whl:

Publisher: publish.yml on devin-griff/drto

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.4.0

2 files

0.3.0

2 files

This release

0.2.1 This release

2 files

0.2.0

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

0.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page