Skip to main content

causal-hybrid-control

ci pypi python license doi docs scorecard

Decisions from logged data, when the data is confounded. chc learns what an action does from logs that a policy wrote, plans actions under limits, and states how far each plan can be trusted.

Most logs were written by someone acting on what they saw: an operations team that paid drivers more when demand spiked, a thermostat that heated harder on cold nights, a retention team that gave discounts to the customers most likely to leave. In such data the action moves together with whatever else drives the outcome. A model fitted to predict the outcome then learns the wrong effect, sometimes with the wrong sign, and a planner that trusts it acts on it. chc is a small JAX library for the step from those logs to a decision:

  1. Identify the effect of each action from the logs, given the causal graph you state, or say that the logs cannot identify it.
  2. Plan a schedule of actions under limits (bounds, budgets, a safety constraint), on a model that keeps the physics you know and learns the rest: ẋ = f_known(x, u) + r_θ(x, u).
  3. Certify the plan: whether the effect was identified, for how many steps the model's error stays inside your tolerance, and how much hidden confounding the safety constraint survives. Each certificate states what it bounds, on what, and under which premises: the scopes.

When nothing in the logs identifies the effect, chc returns no plan rather than a confident wrong one.

The one result

On a confounded log, fitting the action's effect without adjusting for the confounder flips its sign (true +1.0, naive -0.2). Control the true system with each estimate:

controller            cost      regret    viol     ood
causal-CHC            4.59       -0.00    0.00    0.00
oracle                4.59        0.00    0.00    0.00
predictive        13740.08    13735.49    0.97    1.00

The causal controller matches the oracle. The predictive one drives the state the wrong way (x → -20 for a target of +2), violates the constraint on 97 % of steps (viol) and acts entirely outside the logged actions (ood). That is one seed of the pricing task in notebook 5; over 12 seeds the predictive controller's regret is 13734.15 [13732.55, 13735.31] (benchmarks).

Install

pip install causal-hybrid-control    # or: uv add causal-hybrid-control

Python 3.11–3.15. JAX runs it on the CPU. For a GPU or a TPU, install JAX's build through the extra of the same name, for example pip install "causal-hybrid-control[cuda13]"; the installation page lists them all. To work on the library itself, see CONTRIBUTING.md.

Quickstart

From a panel of logs to a schedule and its certificate, in one call. The causal graph is a required argument: leaving it out would mean "adjust for nothing", which is itself a causal claim.

from chc import CausalGraph, Constraint, Lever, Panel, Target, prescribe

panel = Panel.from_frame(logs, unit="region", time="week")  # pandas, polars or a dict
graph = CausalGraph.from_edges(
    [("demand", "incentive"), ("demand", "supply"), ("incentive", "supply"), ("incentive", "wait")]
)

out = prescribe(
    panel,
    adjustment=graph,
    horizon=15,
    dt=0.1,
    tolerance=0.5,
    levers=[Lever("incentive", lo=-2.0, hi=2.0, unit_cost=0.05)],
    target=Target("supply", value=1.0),
    constraints=[Constraint("wait", hi=0.5)],
)

out.certificate.trustworthy_steps  # 15 -- identified, inside the tube's tolerance, barrier met
out.schedule.magnitudes  # (15, 1); raises instead, if the effect is not identified
print(out.report())  # Markdown: decision, both certificate axes, provenance

prescribe adds no estimator of its own. The graph gives the adjustment set, cross-fitted double machine learning gives the action's effect, and the planner and the certificates do the rest. The quickstart runs this end to end, from simulated logs, and reads the report line by line; the expert path builds the model, the cost and the controller by hand.

Examples

Executed notebooks under notebooks/, also on the documentation site. New here? Start with notebook 0.

notebook what it shows
0 Start here: a decision from logs the whole loop on one everyday problem: the trap in the logs, the effect, the plan, and how far to trust it
1 Causal vs predictive control under confounding, predictive control drives the state the wrong way (to −20, target +2); causal control matches the oracle
2 Learning what physics misses a hybrid model recovers an omitted cubic term; multi-step training cuts drift from noisy measurements
3 The causal inference toolkit adjustment, IV/2SLS, double ML, sensitivity and refutation, side by side
4 An epidemic under a capacity cap flatten the curve down to hospital capacity; pessimism against a greedy controller
5 The benchmark scoreboard regret against an oracle on pricing, inventory and support-shift tasks
5 Robust control under hidden confounding when no adjustment set exists: a sensitivity level Γ, a pessimism radius, a minimax action, and when it pays
6 Cruise control from fleet logs Simpson's paradox in fleet logs; the effect by adjustment or IV; control with the adjusted effect
7 Real data: LaLonde the naive estimate flips sign; adjustment and double ML land inside the randomised experiment's 95% interval
8 Splitting an advertising budget three channels, one budget: why the best split equalises the next euro's return, and when TV switches on
9 Heating a room on a winter night a thermostat's logs, the weather that confounds them, and a night plan that keeps the room warm

Case studies, with what each printed, are on the documentation site: pricing under confounding, an epidemic, a pendulum, media budgets, marketplace dispatch, driver supply end to end and confounded incentives in closed loop, one script each here, and a heat pump on a live building emulator, run in causaldyn-bench.

What's inside

area modules in one line
hybrid dynamics dynamics residual integrate symbolic known physics plus a learned residual (MLP, RBF-KAN, graph, control-affine, port-Hamiltonian, Lipschitz-certified, spectral), rolled out with RK4
identification dynamics_id causal estimators gmethods train frames the action's causal effect from confounded logs: adjustment, IV/2SLS, double ML, the g-formula, sensitivity, refutation
planning and control plan control mpc cost lqr splitting adjoint constrained optimal control and MPC on the fitted plant, with an error tube and a safety audit
decisions from a panel decision panel graph prescribe: adjustment set, effect, plan and certificate in one call
offline safety support uncertainty evaluation offpolicy pessimism, calibrated uncertainty, error tubes, a plan's value from logs
hidden confounding sensitivity barrier reachability regret what unmeasured confounding can do to a plan's cost and its safety, and control that hedges it
experiments and deployment experiment switchback gate misspecification which experiment to run first, how to read a switchback, an anytime-valid deployment gate
causal frontier did scm irf toeplitz delay discovery independence network_causal pathway staggered DiD, synthetic control, dynamic effects, delays, lagged structure discovery
media mix response allocation dlm lift geo_world mmm response curves, a budget's split, a dynamic linear model, lift tests, geo worlds
markets and games marketplace zones matching transport meanfield games koopman mintime control under interference, optimal transport, mean-field control, Stackelberg games
end to end and evaluation spine benchmark causal_bench flagship lalonde metrics surrogate one decision through every layer, oracle-regret leaderboards, real-data LaLonde
scientific computing epidemic galerkin deep_galerkin epidemic control, Galerkin FEM, neural PDE solvers

Every module, with what it does and what was measured: what's inside.

How it is checked

Symbolic results are derived in Maxima and cross-checked in PARI/GP and Octave (validation/). The algebraic cores of the control and guarantee invariants are proved in Rocq (proofs/), with MathComp for the matrix statements. A published statistical result a proof relies on enters it as a named, cited premise, and each file's header says what it proves and what it assumes (theory).

Status

Early, single-author research code, before 1.0. Both halves have been checked on real targets: the identification on the LaLonde data against its randomised experiment (notebook 7), and the control loop on a live BOPTEST building emulator, where it beat the tuned baseline controller on four KPIs of five and drew a 2.0 % higher peak demand (case study).

What each module promises before 1.0 (stable, evolving or experimental) and the roadmap are in the API reference. The changelog is written to be read before upgrading, scope corrections and retractions included. Every release artifact carries a PEP 740 attestation and SLSA build provenance; SECURITY.md says how to verify one.

How it compares

DoWhy and EconML estimate effects; Meridian, PyMC-Marketing and Robyn model media; do-mpc and d3rlpy plan or learn a policy on a model you trust. chc works at the seam between them: from a confounded log to a schedule and its certificate, in one place. It composes ideas that exist — hybrid dynamics, pessimistic offline control, sequential causal identification, differentiable control — and its contribution is the integration behind one API, with a benchmark whose interventional effects are known. The comparison row by row, and when not to use chc: why, and when not to.

Contributing and citation

CONTRIBUTING.md lists the gates a change has to pass: ruff, ty, the pytest suite, and rocq compile over proofs/*.v. Machine-readable citation metadata is in CITATION.cff; every release is archived on Zenodo.

@software{gradina_causal_hybrid_control,
  author  = {Gradina, Ilia},
  title   = {causal-hybrid-control: physics-structured dynamics with a learned causal residual},
  year    = {2026},
  version = {0.14.3},
  doi     = {10.5281/zenodo.21737789},
  license = {Apache-2.0},
  url     = {https://github.com/causaldyn/causal-hybrid-control}
}

The doi is the concept DOI: it resolves to the newest release rather than freezing at the version above, so a reader following the citation lands on current code.

License

Apache-2.0 © Ilia Gradina, with a NOTICE. Releases up to 0.10.0 stay under MIT.

Metadata

Release files for causal-hybrid-control 0.14.3

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

Source distribution (sdist)

Source distribution for causal-hybrid-control 0.14.3
File Size Uploaded
causal_hybrid_control-0.14.3.tar.gz 3.5 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for causal-hybrid-control 0.14.3
File Interpreter ABI Platform
causal_hybrid_control-0.14.3-py3-none-any.whl Python 3 none any Details

Total release size: 4.1 MB

Release files / causal_hybrid_control-0.14.3.tar.gz

Download URL causal_hybrid_control-0.14.3.tar.gz
Size 3.5 MB
Tags Source
SHA-256 checksum
How to use checksums
fb44fa0da69b85055c11a9285f3a4c1d1185f65d82ae89e112ddc7d0c26d93de
BLAKE2b-256 checksum
How to use checksums
49ade395df5b519fda09d1c1aad9abfd55228d5b21182a8ba1581115b7822be2
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 Oct 7, 2026.

Transparency log

Release files / causal_hybrid_control-0.14.3-py3-none-any.whl

Download URL causal_hybrid_control-0.14.3-py3-none-any.whl
Size 667.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a6345b55427d82de23ceb1142e2a6c69b03d3a3c8a9bb3c5d24c570fb19c9100
BLAKE2b-256 checksum
How to use checksums
2e83df02a6da6103c3929908e16d049e736d5ad604cf754c2c77056ab3336dac
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 Oct 7, 2026.

Transparency log

Release history Release notifications | RSS feed

0.18.0

2 release files

0.17.0

2 release files

0.16.0

2 release files

0.15.1

2 release files

This release

0.14.3 This release

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release 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