Batch mid-course correction, step 2: modelling substrate, projection, and the correction QP - #516
Open
kgdunn wants to merge 13 commits into
Open
Batch mid-course correction, step 2: modelling substrate, projection, and the correction QP#516kgdunn wants to merge 13 commits into
kgdunn wants to merge 13 commits into
Conversation
Phase 2 of the batch mid-course correction work, building on the simulator merged in #515. Landing here as one PR in clearly separated commit series: - Batch modelling substrate: BatchPCA, BatchPLS, BatchMonitor, batch plots, dataset loaders (supersedes the stale #459-#462 stack, refreshed to current conventions). - Public partial-observation projection (PCA.project / PLS.project with TSR, SCP and PMP score estimators). - The mid-course correction QP (batch/control.py, osqp behind a new 'control' extra) with hard SPE/T2 cap mode and a no-correction dead band. - Executed policy evaluation on the simulator: replay vs mid-course correction vs feedforward ceiling vs true optimum, with realised (not predicted) gains. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
melted_to_wide, wide_to_dict and wide_to_melted were stubs; they now round-trip the standard batch dictionary, the melted frame and the one-row-per-batch wide frame with the 2-level (tag, sequence) column index. Ported from the stale #459 stack onto current main. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
…plots, loaders Consolidates the stale #459 / #460 / #462 stack onto current main, as one commit series inside the mid-course-correction PR: - BatchPCA: batchwise-unfolded (Nomikos-MacGregor) PCA with an optional initial-conditions (Z) join, composed over multivariate.PCA and MCUVScaler; batch-level scores, SPE, T2, contributions and the plot and limit conveniences. - BatchPCA.predict_online: projection to the model plane for a partially-observed batch (upgraded to the shared missing-data projection API in a later commit series). - BatchMonitor: time-varying online SPE and T2 limits learned from good batches, with per-sample alarms, plus online_monitoring_plot. - BatchPLS: batchwise-unfolded [Z | X] -> Y regression to final quality. Refreshed beyond the original: the class now owns both scalers publicly (center_/scale_ for the unfolded block, y_center_/y_scale_ for the quality block; the inner PLS runs with scale=False), reports beta and RMSE in engineering units, and adds a prediction_interval wrapper. The mid-course corrector reads these public attributes instead of any PLS internals. - time_varying_loading_plot and contribution_at_time_plot for the unfolded structure; dataset loaders load_nylon, load_dryer and load_batch_fake_data for the bundled batch CSVs. - Integration test: BatchPLS on a simulator historical campaign (80 batches, 4 components) reaches fit R2 0.83 and out-of-sample correlation 0.80 against fresh batches; thresholds pinned below with margin. The #461 transformer facades are deliberately not re-landed; they can be revived separately if wanted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
…cp, pmp) The batch-so-far primitive, promoted to the multivariate package where every model benefits: - New shared kernel multivariate/_projection.py implementing the score estimators of Arteaga and Ferrer (2002): trimmed score regression (the default; statistically the strongest in their comparison and in Garcia-Munoz, Kourti and MacGregor 2004's batch-so-far study), single-component projection, and projection to the model plane. For a fixed missingness pattern each estimator is a fixed linear operator on the observed columns; operator_for_pattern exposes that matrix, and project_rows groups rows by pattern so each operator is built once. - PCA.project / PLS.project estimate scores, SPE (over the observed columns), T2, a conditioning diagnostic and the observed count for rows containing NaN; complete rows take the standard path, so their scores are bitwise identical to transform(). PLS.project also returns y_hat on the original quality units. - PCA.projection_matrix / PLS.projection_matrix (and a BatchPLS passthrough) expose the per-pattern operator with its condition number and a documented ridge option; nothing degrades silently. - BatchPCA.predict_online now delegates to the shared kernel (gaining method and ridge parameters; TSR replaces the previous PMP-only path), and the new BatchPCA.predict_online_trace projects every time sample of a batch in one vectorized call. BatchMonitor uses the trace, cutting its nylon fit from 279 s to 1.5 s, and passes a method parameter through so limits and monitored traces always use the same estimator. - BatchPLS stores its scaled training matrix and exposes y_loadings_ and explained_variance_, the pieces the mid-course corrector needs to build per-decision-point reference distributions. - New control extra (osqp) declared in pyproject ahead of the corrector module. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
…he control extra The core of the phase. midcourse_correction is the pure optimisation: the unfolded row splits into observed columns (initial conditions and the past), free columns (the future MV setpoints, the decision variables) and missing future responses; the score vector is the affine image t = b + A_F u of the free columns under the fixed-pattern TSR operator, so quality tracking (or maximisation), movement from the nominal remaining schedule, SPE and Hotelling's T2 are all convex quadratics in u. Box bounds, per-tag rate limits (including the seam to the last implemented sample) and an optional engineering-space knot parameterisation stay linear, so osqp solves the whole program; the unconstrained case falls back to the closed-form solution. Hard SPE/T2 caps run an outer multiplier iteration (geometric escalation plus per-cap bisection), verified in the tests against a direct SLSQP solve of the capped problem. MidCourseCorrector is the decision-point workflow around it: the SPE validity gate on the batch-so-far (Flores-Cerrillo and MacGregor 2004), the no-correction dead band from the model's prediction interval (Yabuki and MacGregor 1997) with a target_side option so a floor-type quality skips batches predicted at or above target, per decision-point SPE limits and score covariance from re-projecting the training batches under the decision point's own missingness pattern (Garcia-Munoz, Kourti and MacGregor 2004), and the assembled schedule frame ready to implement or hand to the simulator. The historical campaign policy's deliberate variation changes from offset-plus-ramp to independent knot offsets: the executed-policy experiments showed offset-plus-ramp cannot identify partial-batch moves, which is precisely the data requirement the mid-course literature states. Executed on the simulator (per-class models, one decision point at day 4), the corrected batches gain +0.62 g/L on average with none harmed; the integration test pins that behaviour. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
…; v1.68.0 evaluate_control_policies runs the whole mid-course workflow end to end on the simulator and reports realised (executed, same-seed counterfactual) quality per policy. Headline, defaults, seed 0, forty fresh batches: replay 7.51 +/- 1.20 g/L; mid-course 7.71 +/- 0.78 (a 35% sigma reduction; four batches corrected, all in the poorest feed class, gaining +1.53 to +2.67 g/L each, none harmed; the worst batch rose from 3.66 to 5.79). The oracle-from-the-decision-point row (the remaining schedule optimised against the simulator itself) shows the data-driven correction captured 63% of what was achievable at that decision point; the perfect-feedforward row raises the mean but leaves a worse low tail than the corrected policy, because a schedule fixed at time zero cannot answer a disturbance that develops mid-batch. A decision-point sweep (documented in the user guide) shows the correction window is mid-batch: earlier, projections are too uncertain and misdirect; later, the remaining schedule has no leverage. Also: agent tools correct_batch_midcourse and evaluate_batch_control_policy; the midcourse_correction analysis recipe; docs/user_guide/batch_control.rst carrying the executed numbers; version 1.68.0 with CITATION.cff and the changelog. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
CI resolves dependencies fresh whenever pyproject.toml changes ahead of the maintainer's manual lockfile refresh, and the fresh resolution on Python 3.13 picked scipy 1.18.1, which only shipped cp312 wheels; every job then failed at the install step. A uv constraint excludes that one release. Drop it once scipy publishes cp313 wheels for it or a newer release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
The Sample/Day/Corrected/Mean-gain simple table had column markers narrower than the widest cells, which docutils rejects and the strict docs build treats as fatal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
…de error audit (#500) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra # Conflicts: # CHANGELOG.md # CITATION.cff
Checked against the primary sources, matching the corrections made to the book chapter that documents this module. - Flores-Cerrillo and MacGregor optimise an adjustment to the scores and recover the trajectories by inverting the PLS model; that inversion is what keeps the result consistent with past operation. The module header previously credited them for a reconstruction step this module does not perform. Both routes are now described, along with why optimising the MV columns directly needs the SPE term and the explicit constraints. - Credit Arteaga and Ferrer for trimmed score regression, which was cited only through Golshan et al. - The SPE check in their paper gates whether a correction is computed at all; say so, and keep the candidate-row SPE penalty marked as an addition here. - With hard SPE and T2 caps the program is quadratically constrained rather than a quadratic program; the user guide now says so. - The user guide claimed the literature almost always reports predicted gains. Simulation studies do execute their corrections; it is industrial case studies that cannot. - Mean corrected gain is +2.02 g/L, not +2.03, matching the measured value and the decision-point sweep table on the same page. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra # Conflicts: # CHANGELOG.md # CITATION.cff # pyproject.toml
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra # Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 2 of the batch mid-course correction work, on top of the simulator merged in #515. This lands as one PR with the phases as clearly separated commit series (the session's git proxy accepts exactly this branch), in this order:
BatchPCA(batchwise-unfolded PCA with optional Z join),BatchPLS([Z | X] -> Y),BatchMonitor(time-varying online SPE/T2 limits), the batch plots, dataset loaders anddata_inputconverters. This consolidates and supersedes the stale Batch modernization phase 1: offline BatchPCA, dataset loaders, converter completion #459, Batch phase 2: online Nomikos-MacGregor monitoring #460 and Batch phase 4: BatchPLS to final quality #462 stack, refreshed to the current conventions (lazy frame descriptors, error-message style, reproducibility contract); the Batch phase 3: sklearn transformer facades and f_rupture #461 transformer facades are deliberately dropped for now and can be revived separately if wanted.PCA.project/PLS.projectfor rows with a missing future (methodin{"tsr", "scp", "pmp"}, TSR primary per Arteaga and Ferrer 2002), exposing the fixed-missingness-pattern linear operator the corrector precomputes per decision point, with a conditioning diagnostic and a documented ridge option.batch/control.py:midcourse_correction(pure function) andMidCourseCorrector, solved with osqp behind a newcontrolextra. Penalty-form QP as the workhorse plus an outer loop on the multipliers for hard SPE/T2 caps; per-decision-point limits; a no-correction dead band from the model's prediction interval; target and maximize modes; rate-of-change and seam constraints; optional knot parameterisation.evaluate_control_policieson the simulator: replay vs mid-course correction vs the feedforward ceiling vs the true optimum, reporting realised (executed, not predicted) gains, plus agent tools, a recipe, and a user-guide page with every number measured from seeded runs.Version, changelog and CITATION.cff mechanics land with the final phase.
Companion PRs: the book chapter that walks through this API is kgdunn/pid-book#272, and its nine figures are kgdunn/figures#83. Suggested merge order: this PR, then the figures PR, then the book PR (whose PDF step stays red until the figures are on that repo's
main).🤖 Generated with Claude Code
https://claude.ai/code/session_01NZAyiPT8xURSdi24yFKCra
Generated by Claude Code