Skip to main content

ADOPT-FPML

CI PyPI Python License

Automatic Discovery of OPTimal hybrid First Principles–Machine Learning models.

ADOPT-FPML discovers a parsimonious information-flow architecture for a system that has a first-principles (FP) model and measured data. It decides which outputs already have adequate FP predictions, where ML blocks are needed, which of four FP–ML interactions to use, what the ML inputs and outputs should be, and when to stop adding complexity.

This repository contains the proposed discovery algorithm, an installable Python package, two complete synthetic case studies, data-generation code, portable pretrained model artifacts, tests, and documentation. It intentionally does not copy full baseline-training programs that are already available in the cited literature.

Publication: Mukherjee, A., Giridhar, N. V. and Bhattacharyya, D. On the Automatic Discovery of Optimal Hybrid First Principles – Machine Learning Models for Interconnected Systems (manuscript under review)

What ADOPT-FPML searches

At every stage, ADOPT-FPML evaluates four reduced-superstructure configurations:

Configuration Package name Information flow ML learns
Parallel parallel FP and ML operate in parallel FP-output residuals
Series I series_1 FP → ML requested system outputs, using at least one FP output as an ML input
Series II series_2 ML → FP row-wise corrections to FP parameters
Integrated integrated ML ↔ FP FP parameter corrections using measured/synthetic inputs

The default algorithm follows the manuscript:

  1. Run the standalone FP model and accept outputs satisfying their output-specific thresholds.
  2. Rank candidate inputs by mean absolute Pearson correlation with unresolved outputs.
  3. For each interaction configuration, add ranked inputs sequentially and retrain the ML block.
  4. Score candidates with corrected Akaike information criterion (AICc) and greedily prune a branch at its first non-improvement.
  5. Select the admissible candidate with the lowest local AICc within the stage.
  6. Retain it only if it resolves at least one new output and its relative global-AICc increase is below tau_AIC.
  7. Screen predicted synthetic variables for relevance, redundancy, and a cardinality cap; propagate retained variables to the next stage.
  8. Stop when all outputs meet their thresholds, no admissible improvement remains, the global-AICc rule rejects a stage, or the stage limit is reached.

See Algorithm and terminology for the route variables and exact decision rules.

Installation

ADOPT-FPML requires Python 3.10 or newer.

python -m venv .venv

Activate it on macOS/Linux:

source .venv/bin/activate

Or Windows PowerShell:

.venv\Scripts\Activate.ps1

Install the released package:

python -m pip install --upgrade pip
python -m pip install adopt-fpml
adopt-fpml doctor

Install directly from a local clone for development:

git clone https://github.com/mukherjeeangan26/ADOPT-FPML.git
cd ADOPT-FPML
python -m pip install -e ".[dev]"
pytest

Use python -m pip install "adopt-fpml[sklearn]" for the optional scikit-learn estimator adapter and mutual-information selector. NumPy, pandas, and SciPy are the only required runtime dependencies.

Quick start on a new system

Prepare two row-aligned DataFrames:

  • inputs: measured/manipulated variables available to FP and ML models.
  • measured_outputs: canonical target outputs, in the same row order.

Then wrap a Python function that returns FP predictions:

import pandas as pd

from adopt_fpml import ADOPTFPML, CallableFirstPrinciplesModel, SearchConfig


def my_fp_model(
    inputs: pd.DataFrame,
    parameters: pd.DataFrame | None = None,
) -> pd.DataFrame:
    gain = 2.0 if parameters is None else parameters["gain"].to_numpy()
    return pd.DataFrame(
        {
            "product": gain * inputs["feed"],
            "temperature": inputs["inlet_temperature"] + 10.0,
        },
        index=inputs.index,
    )


fp = CallableFirstPrinciplesModel(
    my_fp_model,
    output_names=["product", "temperature"],
)

result = ADOPTFPML(fp).fit(
    inputs=inputs,
    measured_outputs=measured_outputs,
    thresholds={"product": 0.05, "temperature": 2.0},  # absolute RMSE defaults
    config=SearchConfig(max_stages=3),
)

print(result.summary())
result.search_history.to_csv("search_history.csv", index=False)

Series II and integrated configurations need a ParameterTargetGenerator; without one, the optimizer records those routes as skipped and still searches parallel/Series I. The E1/E2 examples include bounded SciPy estimators, while a new system normally supplies its own parameter-estimation or inverse-model routine. See Defining your system.

Required choices and defaults

Component You provide Default/fallback How to replace it
FP model predict(inputs, parameters=None) and output names No universal physical model Implement the protocol or wrap a function
Data numeric, finite, row-aligned input/output DataFrames Case-study data are included only for examples Use your own DataFrames
Accuracy rules one rule for every output float means absolute RMSE Use MetricThreshold for MAE, max error, or relative RMSE
ML class/solver optional trainer one-hidden-layer tanh NumPy MLP with Adam and early stopping Implement MLTrainer, or use SklearnTrainer
Input selection optional selector mean absolute Pearson correlation Spearman, mutual information, or a custom selector
Candidate objective optional callable AICc Inject another complexity-aware objective
Branch pruning search configuration greedy first non-improvement patience or moving-window policies
Stage termination search configuration all outputs resolved, no candidate, AICc rule, or stage cap Change SearchConfig

The supplied MLP matches the paper’s model class. It is a reproducible research default, not a claim that one architecture is universally best. If a replacement model is used with AICc, its fitted wrapper must report a meaningful parameter_count.

Reproduce the case studies

Run the portable pretrained architectures without retraining:

adopt-fpml reproduce e1
adopt-fpml reproduce e1 --split test
adopt-fpml reproduce e2
adopt-fpml reproduce e2 --split test

Run the scripts from a clone:

python examples/e1/run_pretrained.py
python examples/e2/run_pretrained.py --split test

Generate E1 data from scratch:

adopt-fpml generate e1 --rows 500 --output e1_training.csv

Generate E2 from an E1 feed trajectory:

adopt-fpml generate e2 --feed e1_training.csv --output e2_training.csv

The longer discovery scripts demonstrate how to rerun structural search. ML optimization can produce small platform-level numerical variations; the portable pretrained runners are the reference path for matching reported predictions. Full details are in E1, E2, and Reproducibility.

Reported retained structures

Case Retained stage 1 Retained stage 2 Standalone FP output
E1, three CSTRs Series I: fp_T_out, T_in, CA0, fp_CB, fp_CC; resolves CB, CC Parallel: fp_T_out, stage-1 T_out, stage-1 CA, T_in; resolves CA, T_out None
E2, cooler/flash Series I: fp_x_A, fp_x_C; resolves seven outputs Integrated: fp_F_liq, T_feed; corrects UA, K_A, K_B, K_C; resolves F_liq, y_A x_C

The manuscript’s third, industrial superheater case is described in the publication but its proprietary plant data and implementation were not supplied for public distribution and are not included here.

Repository map

.
├── src/adopt_fpml/        installable algorithm, interfaces, CLI, cases, data
├── examples/              E1, E2, and a minimal custom-system example
├── docs/                  concepts, extension guides, reproducibility, release guide
├── tests/                 unit, generator, optimizer, and reference-RMSE checks
├── .github/workflows/     CI and trusted PyPI publishing
├── pyproject.toml         package metadata and dependencies
├── CITATION.cff           citation metadata
└── LICENSE                BSD 3-Clause license

See Source archive audit for what was retained, reconstructed, consolidated, or excluded from the original working archives.

Publication, citation, and attribution

Until the article is published, cite the software and provisional manuscript:

@software{mukherjee_adopt_fpml_2026,
  author = {Mukherjee, Angan and Giridhar, Nishant V. and Bhattacharyya, Debangsu},
  title = {ADOPT-FPML: Automatic Discovery of Optimal Hybrid First Principles--Machine Learning Models},
  year = {2026},
  version = {0.1.0},
  url = {https://github.com/mukherjeeangan26/ADOPT-FPML}
}

Update CITATION.cff, this block, and pyproject.toml when the journal citation and DOI are assigned. GitHub displays CITATION.cff through its “Cite this repository” control.

Contributing and support

Bug reports, validation cases, new FP-model adapters, selectors, and carefully tested pruning extensions are welcome. Read CONTRIBUTING.md before opening a pull request. Use GitHub Issues for reproducible software problems; do not include proprietary plant data or credentials.

License and disclaimer

The code is provided under the BSD 3-Clause License. Confirm that this license and all author/affiliation details are acceptable before the first public release. The software is research code supplied without warranty; users are responsible for engineering validation, safety constraints, identifiability checks, and any deployment decision.

First-time maintainers can follow the complete GitHub and PyPI publishing guide.

Metadata

Release files for adopt-fpml 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for adopt-fpml 0.1.0
File Size Uploaded Provenance
adopt_fpml-0.1.0.tar.gz 490.9 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for adopt-fpml 0.1.0
File Interpreter ABI Platform
adopt_fpml-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 967.5 kB

Release files / adopt_fpml-0.1.0.tar.gz

Download URL adopt_fpml-0.1.0.tar.gz
Size 490.9 kB
Tags Source
SHA-256 checksum
How to use checksums
2804ef672905ee70c1a75920d5ed5f3dd70ca2f9c9d4bb48046c1614892b1912
BLAKE2b-256 checksum
How to use checksums
f85df0477dd719ed39b14b161105175bee54fbc730477ef9fdae73282f99b30c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / adopt_fpml-0.1.0-py3-none-any.whl

Download URL adopt_fpml-0.1.0-py3-none-any.whl
Size 476.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
09e00972f1f0d633a5f2905636d8199bb294e08116066ce19bdd5254b895d1c8
BLAKE2b-256 checksum
How to use checksums
13ec5b89861ee26ba8e6cb70423eb28d7dec5fb4ca37f82c7d08f48aa5ead3e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Security for adopt-fpml 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for adopt_fpml-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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