Skip to content

physXAI 1.0.0 - #93

Open
PatrickHenkel1 wants to merge 142 commits into
mainfrom
refactoring_v1.0.0
Open

PatrickHenkel1 wants to merge 142 commits into
mainfrom
refactoring_v1.0.0

Conversation

@PatrickHenkel1

@PatrickHenkel1 PatrickHenkel1 commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator

Release physXAI 1.0.0. This merges the refactoring branch into main. It is a major release and breaks backwards compatibility, except for the AgentLib-MPC integration (agentlib_mpc.machine_learning_plugins.physXAI: custom object names and file layout stay the same, and the contract tests check them).

refactoring_v1.0.0 is 139 commits ahead of main and 0 behind (main up to 0.3.0 is merged already). The CI of the branch tip is green.

Known limitation: exporting recurrent models (RNNModel, PCNNModel) needs AgentLib-MPC with RNN support (branch 143-feature-multistep-model-support), which is not released yet. AgentLib-MPC 1.1.1 loads single step models only. The export is verified against branch 143, but not in the CI of physXAI.

Highlights

  • Expression language physXAI.expr: replaces the constructed features and the Modular* classes of branch 26. The expressions are wired into the model (ModularANN), so the MPC only needs raw inputs. Solvers are adam, ols and qp.
  • Constrained regression with certified shape constraints: ModularANN(px.Linear(terms), solver='qp', shape=ShapeConstraints(...)) replaces ConstrainedRegression.
  • Leakage free data pipeline: BlockSplit with an embargo between the splits, lags and Change(X) derived natively, data on a regular time grid, and the inputs taken from the model (prep.pipeline(path, model=model)).
  • Multi step evaluation and training of single step models: eval_horizon, physXAI.evaluation.rollout, RecursiveTraining, and RMSE / MAE / bias for every step of the horizon.
  • Recurrent models: RNNModel warms itself up (no init model) and is trained on the trajectory in closed loop. The saved step model is the one AgentLib-MPC uses. Also new: PCNNModel (Di Natale et al. 2022).
  • Physics: PINN with one output and normalized loss terms. Trainable physics residuals (PhysicsResidual), with a deterministic calibration.
  • Evaluation: metrics per output, one model report, repeat_training + ModelComparison (with a paired, corrected resampled t-test), and feature selection on the horizon error.
  • Infrastructure:
    • physXAI.io.Run replaces the global Logger, and the standard logging module is used.
    • set_seed sets one global seed.
    • Version is static in pyproject.toml, the dependencies have upper bounds, and constraints.txt pins the tested versions.
    • CI uses the EBC template plus Windows, a smoke run of the examples, and strict ruff and Sphinx checks.
    • Documentation is built with Sphinx/MyST and includes a migration guide.
    • examples/ is a tutorial of 13 scripts, and the tests are in tests/.

The full list is in CHANGELOG.md. The migration from 0.x is in docs/source/migration.md.

Included PRs

#70 foundation and contract tests · #71 data pipeline · #72 expression language · #73 recursive evaluation · #74 RNN · #75 metrics and plots · #76 Run, comparison, docs · #77 comparison of existing runs · #78 CI template and Sphinx · #79 PINN, no legacy code · #80 PCNN and physics residuals · #81 release checklist · #82 examples and tests · #83 shape constraints · #84 release review · #85 deterministic init · #87 review fixes · #88 release fixes · #90 final review · #91 pre-release fixes · #92 release polish

After the merge

Follow docs/release_1.0.0.md:

  1. Wait for the Python CI on main, which fills gh-pages/docs/main/.
  2. Switch GitHub Pages to gh-pages / /docs, then check the pages and the badges.
  3. In a commit on main, replace unreleased in the CHANGELOG entry by the release date. Then tag v1.0.0 and write the release notes, with the known limitation at the top.
  4. Clean up the old branches, the gh-pages folders and the refactoring_v1.0.0 trigger in verify_examples.yml.
  5. In AgentLib-MPC, merge main into branch 143 (the int(model.rank_) fix).

AgentLib-MPC installs physXAI from main in its CI, so from the merge on its tests run against 1.0.0 (tests/test_physXAI_plugin passes with 1.0.0).

🤖 Generated with Claude Code

PatrickHenkel and others added 30 commits October 28, 2025 23:56
PatrickHenkel1 and others added 24 commits November 7, 2026 00:41
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rates given as None are estimated by nonnegative least squares of the single step energy balance on the
steps of the training split (offset to the unforced dynamics), reported in td.physics['initial_rates'].
Seed study (BOPTEST, 10 paired runs, split + init): RMSE over 12 h lower in 8 of 10 runs, -0.05 K on average.
Terms without positive effect in the data start at a weak rate with a warning. Example 10 uses them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Release review 1.0.0: embargo, seeds, shift, unknown arguments, docs
Conflict in the dependencies: the bounds of #84 plus scipy>=1.11,<2 (pinned 1.18.1 in constraints.txt).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Constrained regression as ModularANN(solver='qp') with certified shape constraints
Warm start of hybrid ModularANNs and deterministic calibration of physics residuals
…raining details

- RNN/PCNN reject lags, changes and derived columns of a predicted feature as inputs
  (they held measured values over the horizon)
- Recursive evaluation/training of single step models recomputes Change(T) inputs
  (also lagged or inside derived columns) from the predicted trajectory
- Default embargo covers the reach of Change(X) and of lags inside derived columns;
  docs no longer claim that the embargo removes the autocorrelation
- Shuffle buffer holds all samples (single step networks, physics residuals)
- CMNN/PINN: unknown monotonicity names raise, at least one neuron per activation part
- PreprocessingData(aggregation='mean' | {...}): mean over [t, t + time_step) when
  sub-sampling; warning without aggregation; dropped time stamps are logged
- repeat_training creates every model from its config, init seed also seeds px.RBF
- PCNN rate cache by weak reference instead of id(); Param names survive saving
- Closed form solvers on float64 data; physics residual parameter names must be unique

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mean over [t, t + time_step) depends on whether a time stamp labels the start or
the end of a logged interval, and 'mean' for all columns would average states (leakage).
A sampling design is planned separately, so 1.0.0 only warns on point sampling and asks
to resample interval quantities before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- paired(baseline): run by run differences (mean with t interval, median, share of
  better splits, Wilcoxon p-value), pairing by split seed or run name
- training data config stores a fingerprint of the splits; paired reports pairs on
  different rows (same seed but other block length, e.g. single step vs RNN windows)
- save(run, baseline=...) and --baseline on the command line
- example 11 uses one BlockSplit for all models and shows the paired comparison

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review fixes for 1.0.0: leakage in multi step evaluations, embargo, paired model comparison
Conflicts resolved in favour of 1.0.0: the old CI workflows, requirements.txt and the
copilot instructions were removed on purpose (CI template, constraints.txt), pyproject.toml
keeps the static version 1.0.0 and the bounded dependencies, which are at or above the
security fixes of 0.3.0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed paired t-test

- Rollout: lags (Q_lag1) and changes (Change(Q)) of derived columns depending on the
  recursive feature are recomputed from the predicted trajectory instead of being taken
  from the data (leakage in the horizon metrics, the recursive training and the feature
  selection). Lagged raw columns of their history are the data shifted by the lag.
- shift=0: inputs holding the target through a change of a derived column or nested
  derived columns are rejected (holds_current_value).
- CMNNModel / PINNModel: activation_split defaults to [1, 1, 1]; without monotonicities
  only convex neurons made the prediction convex in all inputs.
- Settings of the split next to a BlockSplit raise a ValueError instead of being ignored.
- Output rescaling keeps the scale 1 for a constant target.
- Multi step embargo without the warmup (it lies inside the split of its sequence).
- ModelComparison.paired: confidence interval and p-value of the corrected resampled
  t-test (Nadeau & Bengio 2003) instead of the plain t interval and Wilcoxon test;
  no correction if all runs share one split; note on multiple testing.
- Feature selection: the score of the selected set is optimistic (validation data).
- Docs: CHANGELOG (unreleased, 0.3.0 entry, requirements.txt wording), README wording of
  the constrained regression, no runtime claims, deleted branches removed from the
  branch review, release checklist: merge main first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1.0.0: release review fixes (rollout leakage, convex CMNN, corrected paired t-test, merge of main)
…o 0.3.0 and branch 26

Unused code: LimitedActivation, the n_features and normalize options of the keras
constructions, extra_targets, RunRecord.extra, SPLITS, CERTIFICATES, an unreachable
output check of PINNModel, legacy fallbacks in TrainingData.load and getattr(td, 'shift').

CHANGELOG and migration guide list the changes relative to 0.3.0 and branch
26-integrate-modular-anns (ConstrainedRegression, ModularPolynomial, ModularFeature);
fixes of intermediate 1.0 states are removed. The docs describe general behaviour
instead of numbers that go stale (seed studies, run times, number of examples,
AgentLib-MPC release). README: model list with the class names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
numpy 2.5 and scipy 1.18 need Python 3.12: numpy 2.4.6 and scipy 1.17.1 are pinned
for Python 3.11 (resolution checked with uv for 3.11, 3.12, 3.13 on Windows and Linux).
Getting started: supported Python versions, 3.14 follows with TensorFlow 2.22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1.0.0: final review (unused code, stale docs, CHANGELOG vs. 0.3.0 and branch 26, constraints for 3.11 - 3.13)
…ing of ModularANN and PCNN, CMNN layers

- check_agentlib_compatibility rejects lag groups without lag 0 (e.g. ['u', 'T_lag1']): AgentLib-MPC accepts them
  but passes the values from lag 0 on (T(k) instead of T(k-1)). physXAI itself keeps isolated lags.
- ModularANN.online_pipeline: no warm start for a loaded model (crashed without build context, would overwrite the
  loaded weights).
- PCNN: trained parameters, consistency margin and initial rates are read from the model (constants built into it),
  not from rates re-estimated on the current data (wrong after online_pipeline on other data).
- CMNNModel, PINNModel and px.MonotoneMLP need n_layers >= 1: without a hidden layer the prediction was increasing
  in every input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ality.yml

Only formatting, no change of the code. The ruff version is pinned in quality.yml and .pre-commit-config.yaml,
since the formatting can change between ruff versions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pre-release fixes: AgentLib export of isolated lags, online training, CMNN layers; ruff format
…ps, atomic Run.save, release date check

- Lags of inputs taken from the model (inputs=None) are kept in the preprocessing config until the
  inputs are resolved, so from_config (repeat_training) trains with the same inputs.
- Numbers of steps given as whole floats (96.0) are steps instead of nanoseconds; other floats raise.
- Run.save checks all target files before writing, a run without overwrite is not left half written.
- Version Check requires a release date in the CHANGELOG entry of the tagged version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Release polish for 1.0.0: lags in the config, steps as floats, atomic Run.save, release date check
@PatrickHenkel1
PatrickHenkel1 marked this pull request as ready for review November 8, 2026 21:08
Copilot AI balanced review requested due to automatic review settings November 8, 2026 21:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

PatrickHenkel1 and others added 3 commits November 9, 2026 23:58
The normalization of the recurrent models used the variance floor 1e-12, so a
constant input column (e.g. a fixed air flow in the training data) was scaled
by 1e6. Any later deviation from the training value, such as a rounded value in
an MPC (0.07222 instead of 0.072222), reached the network as a huge normalized
input; in a PCNN it shifted the hidden states by up to 3.

Constant columns are now normalized with variance 1, as in the single step
models (expr.blocks, ann_models.output_scale). New helper input_variance, used
by build_step_model and build_pcnn_step_model, with a regression test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A loss of the energy accumulator can be scaled by a flow input,
b * V * (T_x - T), e.g. a ventilation with the air flow V and the supply
temperature T_x. Before, every loss had a constant conductance, so a varying
air flow had to be learned by the recurrent network.

- PCNNModel(flows={loss input: flow input}); PCNNTerm.flow
- the step model multiplies the gradient by the flow (keras Multiply, translated
  by AgentLib-MPC); the flow is no input of f, like the controls
- the initial rates given as None are estimated with the scaled term
- the consistency check 1 - sum b > 0 uses the largest flow of the training data
- flows is only written to the config when used

Tests: estimated rate equals the true dt*cp/C of the one room data, closed loop
rollout, config round trip, invalid configurations, CasADi contract.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
 RNN/PCNN: normalize constant inputs with variance 1; PCNN losses scaled by a flow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants