pymc-devs / pymc-devs/pytensor

Blockwise of an OpFromGraph core keeps the inner graph's unknown static shape

Open
#2,419 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

OpFromGraph shape inference vectorization
Dominant language
Python
Stars
644
Forks
208
Avg merge
2d 14h
Merged PRs (30d)
16

Description

vectorize_graph over pt.diag returns a Blockwise{AllocDiag} whose output shape is (?, ?, ?) when the batched input has static core shape (3,), and Shape_i of that output never folds to a constant. AllocDiag is an OpFromGraph, and Blockwise reads the static shape from the inner graph, which was built before the input had a static shape, instead of recomputing it from the batched input. A plain Op core such as Cholesky recomputes and gets (?, 3, 3).

import pytensor.tensor as pt
from pytensor.graph import vectorize_graph
from pytensor.compile.mode import get_mode
from pytensor.graph import FunctionGraph

x = pt.vector("x")  # static shape unknown when diag is built
d = pt.diag(x)

xb = pt.matrix("xb")
db = vectorize_graph(d, replace={x: pt.specify_shape(xb, (None, 3))})
print(db.type)  # Tensor3(float64, shape=(?, ?, ?)), expected (?, 3, 3)

fg = FunctionGraph([xb], [db.shape[2]], clone=True)
get_mode("FAST_RUN").optimizer.rewrite(fg)
print(fg.outputs[0])  # Shape_i{2}.0, expected the constant 3

# Cholesky, a plain Op, recomputes from the batched input:
m = pt.matrix("m")
cb = vectorize_graph(pt.linalg.cholesky(m), replace={m: pt.specify_shape(pt.tensor3("mb"), (None, 3, 3))})
print(cb.type)  # Tensor3(float64, shape=(?, 3, 3))

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the supplied reproduction and inspect vectorize_graph, Blockwise, and OpFromGraph handling of static shapes. Trace why the inner graph retains unknown dimensions instead of using the replaced input shape; done means the batched diag reports (?, 3, 3) and Shape_i of its final dimension folds to the constant 3.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.