Repository navigation
Fix dims coercion to list in model_from_fgraph - #8465
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8465 +/- ##
=======================================
Coverage 91.95% 91.95%
=======================================
Files 128 128
Lines 21276 21276
=======================================
Hits 19564 19564
Misses 1712 1712
🚀 New features to boost your workflow:
|
ricardoV94
left a comment
There was a problem hiding this comment.
I started and then stopped. My posterior is beta(1, 0), that all new tests are overkill, and changing the assertion on the original tests suffices. We can't add 20 tests everytime we fix something like list -> tuple ...
| np.testing.assert_allclose(ip["y_cholesky-cov-packed__"], new_ip["y_cholesky-cov-packed__"]) | ||
|
|
||
|
|
||
| def test_clone_model_preserves_dims(): |
| ], | ||
| ids=["omitted", "single_str", "single_tuple", "two_dims"], | ||
| ) | ||
| def test_dims_forms_roundtrip(dims, shape): |
| "kind", | ||
| ["free_rv", "observed_rv", "deterministic", "potential", "data"], | ||
| ) | ||
| def test_dims_preserved_for_every_var_kind(kind): |
add_named_variable is declared to take a tuple and was passed a list. It stores dims verbatim, so the list reached named_vars_to_dims and the round trip stopped agreeing with itself: >>> model_from_fgraph(fgraph_from_model(m)[0]).named_vars_to_dims == m.named_vars_to_dims False # before True # after Every path built on the pair inherits it, so Model.copy(), copy.copy, copy.deepcopy, pm.do and pm.observe all disagreed with their input too. The tests were part of the defect. They asserted the round trip's own output, ["test_dim"], rather than comparing to the original model, which is why this went unnoticed. They now compare against the original, and that is the assertion that catches the type. Invisible to CI because both files sit in the FAILING mypy baseline. No consumer depends on a list here: backends/arviz.py and backends/mcbackend.py normalise with list(), printing.py and variational/opvi.py ignore the type, and testing.py never reads dims. So this is a contract fix, not a crash fix.
0e663fc to
f17b181
Compare
|
Agreed. Cut it down to the fix plus the assertion changes: Kept out as unrelated: the Say the word if you want the adjacent |
|
Thanks for the review @ricardoV94 ! |
add_named_variableis declared to take a tuple and is passed a listpymc/model/core.py#L2196pymc/model/fgraph.py#L381ModelVarcoerces on the way in regardless,pymc/model/fgraph.py#L37, so thegraph never held a list:
Consequence: the round trip stops agreeing with itself
fgraph_from_modelandmodel_from_fgraphare a pair, so every path built onclone_modelinherits the mismatch:Model.copy(),copy.copy,copy.deepcopypm.dopm.observeInvisible to CI: both files sit in the
FAILINGmypy baseline,scripts/run_mypy.py#L25.No consumer breaks on a list
pymc/backends/arviz.py#L226list(dvals), normalizespymc/backends/mcbackend.py#L57list(...), normalizespymc/printing.py#L430.get(), ignores typepymc/variational/opvi.py#L1174.get(), ignores typepymc/model_graph.py#L355inguard, then iteratespymc/testing.pyassert_equivalent_modelnever reads dimsSo this is a contract fix, not a crash fix.
The tests were the defect
Assertions hardcoded the round trip's output instead of comparing to the original:
tests/model/test_fgraph.py#L65== m_old.named_vars_to_dimstests/model/transform/test_conditioning.py#L136== m_old.named_vars_to_dimstests/model/transform/test_conditioning.py#L234== m.named_vars_to_dimstests/model/transform/test_conditioning.py#L241== m.named_vars_to_dimsAdded
tests/model/test_fgraph.py#L404,#L428,#L451,#L475,#L498,#L520for eachisinstancebranch, each dims spelling,clone_model, ModelVarsubclasses, and the unhandled fallthrough. 13 fail without the one-line change.
Incidental
pymc/model/fgraph.py#L378raisedTypeErrornaming theVariable, so itreported a
TensorVariableand said nothing about whichOpwas unrecognised.Now names the
Op.Not fixed
pymc/model/fgraph.py#L258reads.get(name, ())whilepymc/model/fgraph.py#L37defaults
dims=(), so omitted and explicitdims=()collapse in the graph.Strict xfail at
tests/model/test_fgraph.py#L545. Needs a sentinel or a secondprop on
ModelVar, which touches__props__and all fivemodel_*_rvconstructors. Separately,
else Nonetoelse ()trades one silent loss foranother.