Skip to main content

Conformal prediction and robust decision-making toolkit (PyTorch + CVXPY)

Project description

Robbuffet logo robbuffet

PyPI Python CI Docs

Conformal prediction + robust decision making with PyTorch predictors and CVXPY optimizers.

Install

  • From PyPI (once published):
    pip install robbuffet
    
  • From source:
    git clone https://github.com/yashpatel5400/robbuffet
    cd robbuffet
    pip install .
    
  • Editable + dev extras:
    pip install -e .[dev]
    

Submodules

This repo uses the DCRNN_PyTorch submodule for the METR-LA shortest-path example. Clone with:

git clone --recurse-submodules https://github.com/yashpatel5400/robbuffet

or, if already cloned:

git submodule update --init --recursive

For the METR-LA example, generate predictions via:

cd examples/DCRNN_PyTorch
python run_demo_pytorch.py --config_filename=data/model/pretrained/METR-LA/config.yaml
cd ../..

This writes data/dcrnn_predictions_pytorch.npz that the example consumes.

What this package does

  • Calibrate PyTorch predictors with split conformal prediction and geometry-aware score functions.
  • Produce prediction regions (convex or unions) that can be sampled, visualized (1D/2D), or passed to downstream optimizers.
  • Build deterministic or scenario-based robust decision problems that respect conformal regions.

Supported scores/geometries with closed-form robustification:

  • L2 residual (L2Score) → L2 ball.
  • L1 residual (L1Score) → L1 ball.
  • Linf residual (LinfScore) → Linf ball (hypercube).
  • Mahalanobis residual (MahalanobisScore) → ellipsoid.

Quickstart (split conformal, L2 residual score)

import torch
from torch.utils.data import DataLoader, TensorDataset
from robbuffet import L2Score, SplitConformalCalibrator

# toy predictor
model = torch.nn.Linear(2, 2)

# calibration data loader
x_cal = torch.randn(200, 2)
y_cal = x_cal + 0.1 * torch.randn_like(x_cal)
cal_loader = DataLoader(TensorDataset(x_cal, y_cal), batch_size=32)

cal = SplitConformalCalibrator(model, L2Score(), cal_loader)
alpha = 0.1
cal.calibrate(alpha=alpha)

x_new = torch.randn(1, 2)
region = cal.predict_region(x_new)
print("center:", region.center, "radius:", region.radius)

Scenario-based robust decision making

import cvxpy as cp
import numpy as np
from robbuffet import ScenarioRobustOptimizer, PredictionRegion

# pretend we already calibrated a 2D L2-ball region
region = PredictionRegion.l2_ball(center=np.array([0.0, 0.0]), radius=0.5)

def objective(w: cp.Variable, theta: np.ndarray):
    # linear loss that depends on uncertainty theta
    return cp.sum_squares(w - theta)

def constraints(w: cp.Variable, theta: np.ndarray):
    return [w >= -1, w <= 1]

optimizer = ScenarioRobustOptimizer(decision_shape=(2,), objective_fn=objective, constraints_fn=constraints, num_samples=256)
problem = optimizer.build_problem(region, solver="ECOS")
print("status:", problem.status, "w*:", problem.variables()[0].value)

Visualization

from robbuffet import vis
import matplotlib.pyplot as plt
vis.plot_region_2d(region, grid_limits=((-1, 1), (-1, 1)), resolution=200)
plt.show()

Deterministic closed-form robustification (affine in the uncertainty)

For linear/affine dependence on the uncertain parameter theta, you can avoid sampling and use support functions:

import cvxpy as cp
import numpy as np
from robbuffet import PredictionRegion, robustify_affine_leq, robustify_affine_objective

region = PredictionRegion.l2_ball(center=np.array([0.2, -0.1]), radius=0.3)
w = cp.Variable(2)

# Robust constraint: <w, theta> <= 1 for all theta in region
constr = robustify_affine_leq(theta_direction=w, rhs=1.0, region=region)

# Robust objective: minimize ||w||_2 + worst_case(<c, theta>)
c = w  # example direction depending on w
obj = robustify_affine_objective(base_obj=cp.norm(w, 2), theta_direction=c, region=region)

prob = cp.Problem(cp.Minimize(obj), [constr])
prob.solve(solver="ECOS")
print(w.value)

Examples

  • examples/robust_shortest_path_metrla.py — robust shortest path on METR-LA with conformalized DCRNN_PyTorch forecasts (needs examples/DCRNN_PyTorch submodule + predictions NPZ).
  • examples/robust_bike_newsvendor.py — conformal calibration on UCI Bike Sharing demand + robust newsvendor decisions.

Run with python examples/<script>.py. The METR-LA script assumes you have generated examples/DCRNN_PyTorch/data/dcrnn_predictions_pytorch.npz (see Submodules above).

Trial runner

Use scripts/run_trials.py to run an example multiple times, cache results, and compare robust vs nominal:

# absolute objectives (no normalization)
python scripts/run_trials.py --example robust_bike_newsvendor.py --trials 5 --alpha 0.1

# relative gaps (requires avg_cost_oracle from the example)
python scripts/run_trials.py --example robust_bike_newsvendor.py --trials 5 --alpha 0.1 --relative

Outputs mean/std and a paired t-test (robust < nominal) when scipy is available. Caches results in .cache/run_trials.json.

Extending

  • Add new ScoreFunction implementations that expose their induced region geometry via build_region.
  • For non-convex regions, return PredictionRegion.union([...]) so optimizers can decompose or sample.
  • Use the scenario optimizer as a default inner-approximation; for affine cases use the deterministic robustifiers above.

Contributing

Please open issues for bugs/feature requests and PRs for fixes/additions. See CONTRIBUTING.md for guidelines.

Citation

If you use Robbuffet in academic work, please cite:

@software{robbuffet,
  title = {Robbuffet: Conformal prediction and robust decision making},
  author = {Yash Patel},
  year = {2025},
  url = {https://github.com/yashpatel5400/robbuffet}
}

Project details


Download files

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

Source Distribution

robbuffet-0.0.1.tar.gz (15.7 kB view details)

Uploaded Source

Built Distribution

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

robbuffet-0.0.1-py3-none-any.whl (14.6 kB view details)

Uploaded Python 3

File details

Details for the file robbuffet-0.0.1.tar.gz.

File metadata

  • Download URL: robbuffet-0.0.1.tar.gz
  • Upload date:
  • Size: 15.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for robbuffet-0.0.1.tar.gz
Algorithm Hash digest
SHA256 5c71dffb7456393b4cf9875bde53801523d3b807f5c276f64c68ec8cdf5a4bc3
MD5 3cdcf30ce8fe1b1647f1498def19c5dd
BLAKE2b-256 84295fc805da433de8fb2ac13119b8ecdf849c01b0b7fbad4cf1ca40bd98a89f

See more details on using hashes here.

File details

Details for the file robbuffet-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: robbuffet-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 14.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for robbuffet-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f587ee03914ac49e521d14c64c6db94f14224d0dd53f49aea1a44cc650c99954
MD5 99418e4724a935c66d979eeef8876e84
BLAKE2b-256 048aadd13494ef872a7c2ea8425d9c8de5ec32f0cce0c758d9b1950d752f47d7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page