API contracts and compatibility
This page explains how configuration, data identity, and return values carry through fitting, scoring, and prediction. The package mechanics audit records the corrections made in the source checkout. These audit corrections have not been published to PyPI as part of this work.
Configuration has one source
Every fitting entry point accepts options=Options(...). Pass either that bundle
or the individual option arguments; mixing them raises ValueError.
| Section | Conditional logit | Latent-class logit and CV |
|---|---|---|
fit |
No EM stage; this section does not apply | Initialization, starts, EM stopping, devices, and polishing |
optimization |
Maximum-likelihood solver | Starting fits and both M-steps; also the documented polishing controls |
inference |
Covariance method, grouping, finite-sample correction, and skipping | Same settings; case-level robust is unsupported for a panel mixture |
diagnostics |
check_collinearity controls information reporting |
All diagnostic switches and thresholds |
Mutable inference and diagnostic objects are copied when fitting. Editing an option object later does not relabel an already-computed covariance matrix or change a result's diagnostic configuration.
InferenceOptions(skip=True) skips covariance work and does not require a custom
cluster column to exist. For CV, covariance is skipped when both options and
inference are omitted. An explicit bundle is respected in full: use
Options(inference=InferenceOptions(skip=True)) to request the same behavior.
Use newton_decrement_tol for solver tolerance. Polishing retains its separate
FitOptions.polish_maxiter budget and fixed 1e-10 Newton tolerance; the remaining
solver controls also apply to polishing. FitOptions.score_tol determines LCL's
final convergence flag after EM and polishing. The EM stopping flag is separately
available as em_criterion_met. Binding prices additionally undergo a structural
KKT check: a negative likelihood score at an upper bound still indicates a
feasible improving direction.
Boundary inference modes and their limits are explicit in the options reference and result contracts. A conditional covariance has zero rows for fixed prices, while the class coefficient table suppresses their SEs. Projected mean/SD SEs are separate from that matrix.
For numeraire warnings, NegativeCoefficient.warn_below, when present, overrides
DiagnosticsOptions.near_zero_numeraire_threshold. The
warn_near_zero_numeraire switch still controls the warning status.
Specifications and overrides
LCLSpec.classes defaults to two. The direct constructor retains its historical
five-class default when neither spec nor num_classes is supplied. Specify the
class count explicitly when moving between these interfaces.
Explicit constructor class counts and coefficient floors override the base
specification; omitted values inherit it. A conflicting numeraire name raises an
error. A single explicit design override in fit or CV replaces the corresponding
base-specification design. Supplying both a formula and an explicit variable list
for the same design at the same configuration level raises an error.
If a formula supplies the choice outcome and choice_col is also supplied, they
must agree. Choices must be binary before conversion to boolean, with exactly one
chosen alternative per (panel, case).
LCLSpec freezes top-level fields; its nested variable lists and mappings should
be treated as read-only. Derive changes with dataclasses.replace.
Create a new model instance for each fit. An attempted second fit raises an error before changing the original result's model specification.
Data identity and weights
Separate dems_data is joined by panel ID before evaluating utility or membership
features. It may supply utility interactions even without a membership formula.
External columns must not overlap the choice frame except for the panel ID, and
membership variables must be constant within panel.
Tabular prediction reuses fitted formula transformations and categorical levels. Supply raw columns, including categorical columns, rather than constructing new dummies. Unseen categories raise an explicit error. Prediction identifier columns come from the fitted encoder.
LCL array prediction accepts NumPy arrays, JAX arrays, and ordinary sequences:
| Argument | Shape and ordering |
|---|---|
X |
(rows, alt_vars), in fitted expanded-column order |
alts, cases, panels |
(rows,), aligned with X; original IDs are preserved |
dems |
(panels, dem_vars), in fitted membership-column order |
dem_panel_ids |
(panels,), identifies demographic rows for alignment |
Without dem_panel_ids, demographic rows follow sorted unique panel-ID order.
Do not combine tabular data with array arguments. dems_data requires tabular
prediction; array prediction uses dems.
Historical choices may cover a subset of prediction consumers. Prediction
demographics supply membership priors. PastChoicesData.dems remains accepted
for compatibility, but does not override those priors; historical utility
interactions must already be represented in its X.
| Weight argument | Applies to | Vector ordering |
|---|---|---|
CL fit(..., weights=...) |
Estimation | First appearance of each choice situation in the input |
CL loglik(..., weights=...) |
Scoring | Same rule as fitting |
Both predict(..., panel_weights=...) methods |
Aggregate summaries | Sorted unique prediction-panel order |
Prefer a column or ID-keyed mapping when row order may change. When case IDs
repeat across panels, CL weight mappings use (panel_id, case_id) keys. Scoring
weights are explicit: omitting them scores cases equally and does not reuse
training weights. Prediction weights affect summaries, while individual choice
probabilities remain unchanged.
Return values
Both fit methods return result objects, and both predict methods return
prediction objects. Tables are Polars DataFrames.
| Operation | Conditional logit | Latent-class logit |
|---|---|---|
| Canonical result attributes | converged, cov_matrix, adjusted_bic |
Same |
| Covariance labels | parameter_names() |
Same |
| Probabilities | prediction.predicted_probs |
Same |
| Aggregate predictions | market_shares, aggregate_elasticities, mean_surplus, mean_surplus_change |
Same |
| Per-profile WTP | marginal_wtp(target) |
Same |
| WTP summary | wtp(target), with compute_wtp and tradeoff aliases |
compute_wtp(*WTPRequest), with tradeoff alias, for demographic partitions |
| Contribution scoring | loglik(data, per_case=True) |
loglik(data, per_panel=True) |
CL scoring tables include both panel and case identifiers, so repeated case
IDs remain distinguishable. Their weighted contributions sum to the total from
the same loglik call.
Aggregate uncertainty methods accept se="delta", se="bootstrap", and
se="none"; bootstrap draws and seeds are forwarded to the shared inference
implementation. Summary printing can be disabled with show=False where offered.
Compatibility surface
| Older argument or name | Current usage |
|---|---|
OptimizationOptions.gradient_tol |
Use newton_decrement_tol. Passing the alias warns; reading returns the resolved value. dataclasses.replace operates on the canonical field. |
| Individual fit option arguments | Still supported. Do not mix with options=. |
results.convergence, results.covariance, results.abic |
Deprecated aliases for converged, cov_matrix, and adjusted_bic. |
| CL prediction identifier keywords | Redundant and deprecated. Supplied names must match the fitted encoder. |
FitOptions.start_method |
Only "panel_partition" is implemented; other values raise an error. |
WTPRequest.bins |
A finite, increasing list for "custom_breaks" only. Integer bin counts and bins for other partition types are unsupported. |
The package uses jaxtyping annotations for JAX and NumPy arrays, including
internal solver state and identifier shapes. Public input aliases preserve the
accepted array and sequence forms; ingestion validates values and converts
numerical designs to 64-bit arrays. Scalar arrays have shape ""; general
nonlinear targets retain variable output shapes. Runtime type checking and
explicit value checks complement each other.
Coefficient coordinates
Taste coefficients are stored directly in economic units. NegativeCoefficient
enforces beta <= -min_abs during optimization. Conditional-logit init_beta
uses those same units; infeasible entries are projected onto their bounds.
flat_params and cov_matrix use one common layout. For CL, it is the coefficient
vector in design-column order. For LCL, it is the coefficient matrix in row-major
(variable, class) order followed by non-baseline membership logits. There is no
separate transformed parameter vector or covariance. parameter_names() labels
this layout. Gaussian parameter simulation uses unmodified coefficient draws.
WTP and monetary surplus screen the fitted marginal probability above each
numeraire bound at 0.001, independently of seed and draw count; shares and
elasticities omit this denominator screen. denominator_diagnostics() reports
Gaussian probabilities above the configured bound and above zero, denominator
SEs, and the screening cutoff. This policy does not guarantee finite ratio
moments or provide boundary-aware uncertainty; see price optimization.