Skip to content

tests: add xfail tests for float lapse_dist bugs in _apply_lapse_model#962

Open
cpaniaguam wants to merge 1 commit into
add-choice-only-rlssm-model-to-registryfrom
fix-apply-lapse-model-for-choice-only
Open

tests: add xfail tests for float lapse_dist bugs in _apply_lapse_model#962
cpaniaguam wants to merge 1 commit into
add-choice-only-rlssm-model-to-registryfrom
fix-apply-lapse-model-for-choice-only

Conversation

@cpaniaguam
Copy link
Copy Markdown
Collaborator

@cpaniaguam cpaniaguam commented May 15, 2026

@AlexanderFengler @digicosmos86 Would it be sensible to address this?

Summary

Adds two xfail(strict=True) tests that document two latent bugs in _apply_lapse_model (in dist.py). The tests are currently expected to fail and will flip to passing once a fix is added.


Background

For choice-only models (e.g. softmax_inv_temperature_2), _check_lapse sets self.lapse = 1 / n_choices — a plain float. This float is stored as HSSMRV._lapse and passed to _apply_lapse_model(lapse_dist=...) during prior/posterior predictive sampling. The existing code assumes lapse_dist is always a bmb.Prior object, so two things go wrong.


Bug 1 — AttributeError on lapse_dist.args

_apply_lapse_model always executes:

lapse_rt = pm.draw(
    get_distribution_from_prior(lapse_dist).dist(**lapse_dist.args), ...
)

When lapse_dist is 0.5 (a float), lapse_dist.args raises:

AttributeError: 'float' object has no attribute 'args'

Trigger: any call to model.sample_prior_predictive() or model.sample_posterior_predictive() on a choice-only model that has p_outlier != 0.


Bug 2 — 2-column replace mask for a 1-column output

Even if Bug 1 were somehow bypassed, the replacement mask is always built as:

replace_mask = np.stack([replace, replace], axis=-1)  # always 2 columns

Choice-only simulation output has only 1 column (response; no RT). The 2-column mask either silently corrupts the array via np.putmask broadcasting or raises a shape error depending on input dimensions.

Trigger: same as Bug 1.


Current status

Both bugs are latent on the add-choice-only-rlssm-model-to-registry branch. For RLSSM models ssms_rng_fn raises before reaching _apply_lapse_model (ssm_simulators does not support 2AB_RescorlaWagner_Softmax), so neither bug is reachable through the RLSSM path today. They would be reachable for any other choice-only model supported by ssm_simulators (e.g. softmax_inv_temperature_2) the moment a user passes p_outlier != 0.


Fix (tracked separately)

Add an isinstance(lapse_dist, float) branch in _apply_lapse_model that:

  • skips RT sampling (there is no RT column)
  • samples replacement responses uniformly over choices
  • handles both 1-D (n_obs,) and 2-D (n_obs, 1) sims_out

The type annotation of make_hssm_rv's lapse parameter should also be updated from bmb.Prior | None to bmb.Prior | float | None.

@cpaniaguam cpaniaguam marked this pull request as draft May 15, 2026 13:53
@cpaniaguam cpaniaguam marked this pull request as ready for review May 15, 2026 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant