Skip to content

Refactor transformed_conditional_logp to remove IR dummy Ops (issue #8100)#8101

Open
mikjkd wants to merge 2 commits intopymc-devs:mainfrom
mikjkd:transform_value_update
Open

Refactor transformed_conditional_logp to remove IR dummy Ops (issue #8100)#8101
mikjkd wants to merge 2 commits intopymc-devs:mainfrom
mikjkd:transform_value_update

Conversation

@mikjkd
Copy link

@mikjkd mikjkd commented Feb 9, 2026

Description

Replace the TransformValuesRewrite mechanism with a simpler two-stage approach as suggested by Ricardo Vieira in the issue #8100 : apply transform.backward() before conditional_logp, then add Jacobian correction afterward. This eliminates TransformedValue and TransformedValueRV dummy Ops from the intermediate representation.

Related Issue

Checklist

Type of change

  • New feature / enhancement
  • Bug fix
  • Documentation
  • Maintenance
  • Other (please specify):

Replace the TransformValuesRewrite mechanism with a simpler two-stage
approach as suggested by Ricardo Vieira in the issue: apply
transform.backward() before conditional_logp, then add Jacobian
correction afterward. This eliminates TransformedValue and
TransformedValueRV dummy Ops from the intermediate representation.

Closes pymc-devs#8100
Copilot AI review requested due to automatic review settings February 9, 2026 17:21
@welcome
Copy link

welcome bot commented Feb 9, 2026

Thank You Banner]
💖 Thanks for opening this pull request! 💖 The PyMC community really appreciates your time and effort to contribute to the project. Please make sure you have read our Contributing Guidelines and filled in our pull request template to the best of your ability.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors transformed_conditional_logp to avoid the TransformValuesRewrite/dummy-Op based transform injection by computing logp on back-transformed (constrained) values first and then adding Jacobian corrections afterward, aligning with the two-stage approach proposed in issue #8100.

Changes:

  • Replaced TransformValuesRewrite usage in transformed_conditional_logp with explicit transform.backward() pre-processing and post-hoc Jacobian correction.
  • Added explicit RV-detection checks and a replacement pass (replace_rvs_by_values) for conditional dependencies.
  • Updated a regression test to no longer expect TransformedValue warnings (only ValuedVar remains).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
pymc/logprob/basic.py Implements the two-stage transformed logp derivation (back-transform before conditional_logp, Jacobian after) and removes the rewrite-based approach.
tests/logprob/test_basic.py Updates warning expectations to reflect removal of TransformedValue from the final/evaluated graph.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 620 to 622
rvs_to_values: dict[Variable, Variable],
rvs_to_transforms: dict[Variable, Transform],
jacobian: bool = True,
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type hint for rvs_to_transforms should allow None (and possibly missing keys). Model.create_value_var stores transform which can be None, and this function checks transform is not None, so the current dict[Variable, Transform] annotation is inconsistent and breaks type checking.

Copilot uses AI. Check for mistakes.
"""Compute conditional log-probabilities for RVs, applying value transforms and Jacobian corrections.

This helper will only return the subset of logprob terms corresponding to `rvs`.
All rvs_to_values and rvs_to_transforms mappings are required.
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docstring says "All rvs_to_values and rvs_to_transforms mappings are required", but the implementation treats missing entries in rvs_to_transforms as "no transform" (and there are callers that pass {}). Please update the docstring to match the actual contract (or enforce the requirement with an explicit check).

Suggested change
All rvs_to_values and rvs_to_transforms mappings are required.
All `rvs` must appear in ``rvs_to_values``. Entries in ``rvs_to_transforms`` are
optional; RVs missing from this mapping are treated as having no transform.

Copilot uses AI. Check for mistakes.
Comment on lines +658 to +660
f"Random variables detected in the logp graph: {measurable_logp_terms}.\n"
"This can happen when mixing variables from different models, "
"or when CustomDist logp or Interval transform functions reference nonlocal variables."
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The early measurable_logp_terms error message describes mixing models / nonlocal references, but this specific check is triggered when a logp term itself is a MeasurableOp/RandomVariable output (e.g., a CustomDist logp function returning an RV). Consider adjusting the message (or splitting messages) so it points to the actual failure mode and suggested fix.

Suggested change
f"Random variables detected in the logp graph: {measurable_logp_terms}.\n"
"This can happen when mixing variables from different models, "
"or when CustomDist logp or Interval transform functions reference nonlocal variables."
"Invalid logp terms: some logp outputs are themselves RandomVariables/MeasurableOps.\n"
f"Offending logp terms: {measurable_logp_terms}.\n"
"This usually happens when a CustomDist logp or transform function returns a random "
"variable (e.g., by calling a distribution constructor) instead of a numeric log-density "
"tensor. Ensure that your custom logp/transform functions return a deterministic tensor "
"representing the log-probability, and do not create or return RandomVariables."

Copilot uses AI. Check for mistakes.
Using constrained value expressions (transform.backward(...)) as the keys passed to conditional_logp means conditional_logp can no longer name logp terms via original_value.name (it will often be None for these intermediate expressions). If logp term names are relied on for debugging/traceability, consider propagating a meaningful name from the original unconstrained value var / RV (e.g., set a name on val_constrained or re-name the retrieved logp term).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor value transform logic in logprob to avoid dummy Ops and complex rewrites

1 participant