A Blockwise whose batch dims are all broadcastable is unbatched by local_useless_unbatched_blockwise into core_op(squeeze(expand_dims(x))), and the compiled graph keeps that Squeeze/ExpandDims pair. The rewrite is registered at optdb position 60, after every DimShuffle-collapsing pass, so merge3 at position 100 sees Cholesky(A) and Cholesky(squeeze(expand_dims(A))) as different nodes and a positive-definite matrix used both batched and unbatched is factored twice.
import pytensor
import pytensor.tensor as pt
A = pt.matrix("A", shape=(5, 5))
b = pt.tensor("b", shape=(3, 5, 1))
logdet = 2 * pt.log(pt.diagonal(pt.linalg.cholesky(A))).sum()
quad = (b * pt.linalg.solve(A, b, assume_a="pos", b_ndim=2)).sum()
pytensor.dprint(pytensor.function([A, b], logdet + quad))
Composite{((2.0 * i1) + i0)} [id A] 9
├─ FusedElemwise{Mul, reduce[add@(0, 1, 2)]} [id B] 8
│ ├─ b [id C]
│ └─ [Blockwise{CholeskySolve{lower=True, b_ndim=2, overwrite_b=False}, (m,m),(m,n)->(m,n)}] [id D] 7
│ ├─ ExpandDims{axis=0} [id E] 6
│ │ └─ Cholesky{lower=True, overwrite_a=False} [id F] 5
│ │ └─ Squeeze{axis=0} [id G] 4
│ │ └─ ExpandDims{axis=0} [id H] 3
│ │ └─ A [id I]
│ ├─ b [id C]
│ └─ [5 1] [id J]
└─ FusedElemwise{Log, reduce[add@(0,)]} [id K] 2
└─ ExtractDiag{offset=0, axis1=0, axis2=1, view=True} [id L] 1
└─ Cholesky{lower=True, overwrite_a=False} [id M] 0
└─ A [id I]
The same pair with no solve involved:
pytensor.dprint(pytensor.function([A], [pt.linalg.cholesky(A), pt.linalg.cholesky(A[None])]))
Cholesky{lower=True, overwrite_a=False} [id A] 4
└─ A [id B]
ExpandDims{axis=0} [id C] 3
└─ Cholesky{lower=True, overwrite_a=False} [id D] 2
└─ Squeeze{axis=0} [id E] 1
└─ ExpandDims{axis=0} [id F] 0
└─ A [id B]
A
Blockwisewhose batch dims are all broadcastable is unbatched bylocal_useless_unbatched_blockwiseintocore_op(squeeze(expand_dims(x))), and the compiled graph keeps thatSqueeze/ExpandDimspair. The rewrite is registered at optdb position 60, after every DimShuffle-collapsing pass, somerge3at position 100 seesCholesky(A)andCholesky(squeeze(expand_dims(A)))as different nodes and a positive-definite matrix used both batched and unbatched is factored twice.The same pair with no solve involved: