pytyche.bcf.dispatch

Auto-selecting BCF entry point — pytyche.fit.

Inspects the extracted outcome array from an ObservedExperimentData and dispatches to the appropriate BCF fit function:

  • fit_binary_bcf — Y ⊆ {0, 1} (conversion-rate metric)

  • fit_hurdle_bcf — float Y with ≥ 30% zeros and a positive non-zero tail

  • fit_continuous_bcf— float Y with < 30% zeros (all-positive revenue etc.)

The 30% threshold was chosen to match e-commerce revenue zero-inflation characteristics: at zero share below 30% the hurdle model’s binary sub-model has too few signal events to fit reliably, and a continuous model on the positive-heavy distribution gives equivalent results. The threshold is an internal tunable (_HURDLE_THRESHOLD); it is not yet user-facing — expose as a kwarg if user feedback warrants.

Decision table:

Y all-zero               → ValueError (ambiguous: binary-all-zero vs hurdle-all-zero)
Y ⊆ {0.0, 1.0}, K=2     → fit_binary_bcf
Y ⊆ {0.0, 1.0}, K≥3     → NotImplementedError (reference: multi-arm-joint-hurdle-bcf)
zero_share ≥ 0.30, K≥2  → fit_hurdle_bcf  (any K)
else, K=2                → fit_continuous_bcf
else, K≥3                → NotImplementedError (reference: multi-arm-joint-hurdle-bcf)

Public surface

_dispatch_fit(observed) — pure function; returns the selected callable. fit(observed, ...) — calls _dispatch_fit then forwards to the result.

Functions

fit(observed, *[, observed_copy, ...])

Fit BCF on observed, auto-selecting the model from the outcome shape.

pytyche.bcf.dispatch.fit(observed, *, observed_copy='view', calibration=None, seed=0, **kwargs)[source]

Fit BCF on observed, auto-selecting the model from the outcome shape.

Dispatches to fit_binary_bcf(), fit_continuous_bcf(), or fit_hurdle_bcf() based on the outcome array extracted from observed (see _dispatch_fit for the full decision table).

**kwargs are forwarded verbatim to the selected fit function. This means:

  • pooling= reaches fit_hurdle_bcf() without issue.

  • pooling= passed when binary or continuous is dispatched raises TypeError from GPUBCFConfig (that is a caller error; the error is loud and intentional).

Implementation note: fit calls _dispatch_fit, which runs the extract_fit_arrays adapter to inspect Y; then the selected wrapper runs extract_fit_arrays again internally. That double extraction is deliberate for v0.2 — extraction is cheap relative to MCMC and one-correct-path beats plumbing an extraction bypass. A future optimizer can thread the arrays through if profiling shows cost.

Parameters:
  • observed (ObservedExperimentData) – Observed experiment data.

  • observed_copy (Literal['view', 'deep', 'ref']) – Copy mode for stashing the observed data on the result. 'view' (default) — zero-copy read-only view; 'deep' — independent deep copy; 'ref' — identity (no copy).

  • calibration (Calibration | None) – Optional SBC-fitted artifact applied post-fit by the selected entry point — sugar for .apply_calibration(...) on the result. None (default) returns the raw posterior.

  • seed (int) – Random seed forwarded to GPUBCFConfig.

  • **kwargs (Any) – Additional keyword arguments forwarded verbatim to the selected fit function (e.g., num_mcmc, num_burnin, num_trees_mu, pooling).

Return type:

BinaryBCFResult | ContinuousBCFResult | HurdleBCFResult

Returns:

BinaryBCFResult, ContinuousBCFResult, or HurdleBCFResult — whichever the selected fit function returns.

Raises:
  • ValueError – Unknown metric or all-zero Y (ambiguous dispatch); or, propagated from the selected fit, a supplied calibration whose fitted regime does not match the observed data.

  • NotImplementedError – K≥3 with binary or continuous Y.

  • TypeError – If **kwargs contains unknown GPUBCFConfig field names, or if a kwarg collides with an explicit parameter of this function (standard Python duplicate-keyword-argument error).