Could not broadcast error - works with pm.draw and the graph vis shows no problems

Hi All,

I’m trying to estimate mic position (Nmics,3 shape) and source location (Nsources,3 shape) given a set of time-differences of a sound’s arrival through approximate Bayesian Computing.

I’m constantly getting

ValueError: Could not broadcast dimensions. Incompatible shapes were [(ScalarConstant(ScalarType(int64), data=np.int64(5)), ScalarConstant(ScalarType(int64), data=np.int64(3))), (ScalarConstant(ScalarType(int64), data=np.int64(16)), ScalarConstant(ScalarType(int64), data=np.int64(3)))].

This is even though I’ve used pm.draw andpm.model_to_graphviz to double-check - and everything is as expected however, the error message keeps popping up - and so I’m seeking help here. Any answers/suggestions would be greatly appreciated!

This is the minimal setup:

# -*- coding: utf-8 -*-
"""
Created on Sun Feb  8 01:16:15 2026

"""
import numpy as np
import pymc as pm 
import pytensor as pt
import arviz as az
from itertools import combinations


    
def mic_pair_combis(nchannels):
    '''
    '''
    return list(combinations(range(nchannels), 2))


# simulate to showcase 
nmics = 16 
# nmic rows with x,y,z for each column
mics_xyz = np.random.choice(np.arange(10),3*nmics).reshape(nmics,-1)
nsources = 5
# simulate nsources with x,y,z coordinates in rows
sources = np.random.choice([0,1],3*nsources).reshape(nsources,-1)



def dummy_simulation(sources, micdisp):
    final_micxyz = mics_xyz + micdisp
    nsources = sources.shape[0]
    tdoa_pairs = len(mic_pair_combis(final_micxyz.shape[0]))
    return np.zeros((nsources, tdoa_pairs))


def pm_dummy(rng, sources, micdisp, size):
    '''Does nothing at all - just outputs correct shape output np.array
    '''
    return dummy_simulation(sources, micdisp)

sim_obsdata = dummy_simulation(sources,
                                                    mics_xyz)
rows = int(sim_obsdata.shape[0])    

if __name__ == "__main__":
    
    with pm.Model() as simmodel:
        # source locations
        x1 = pm.Uniform('x1', -10,10, shape=rows)
        y1 = pm.Uniform('y1',  -10,10, shape=rows)
        z1 = pm.Uniform('z1',  0,4, shape=rows)
        # all source positions
        all_sources = pm.Deterministic('all_sources',
                                       pm.math.stack((x1,y1,z1), axis=1))
        
        # mic displacements
        xdelta = pm.Uniform('xdelta', -0.2,0.2, 
                                      shape=nmics)
        ydelta = pm.Uniform('ydelta', -0.2,0.2,
                                      shape=nmics)
        zdelta = pm.Uniform('zdelta',-0.2,0.2,
                                      shape=nmics)
        xyzdelta = pm.Deterministic('xyzdelta',
                                    pm.math.stack((xdelta, ydelta, zdelta), axis=1))
        
        sim_model = pm.Simulator('sim_model',
                                 pm_dummy,
                                 params=[all_sources,
                                        xyzdelta], 
                                  observed=sim_obsdata, 
                                  epsilon=1e-2)
        idata_lzz = pm.sample_smc()
    
    for rv, shape in simmodel.eval_rv_shapes().items():
        print(f"{rv:>11}: shape={shape}")
     pm.model_to_graphviz(simmodel)
   

From the graph visualisation we see that the all_sources variable is 5,3 as expected, and the xyzdelta is 16,3 as expected - and I’ve done pm.draw as shared before to reproduce simulated data…
Any help would be appreciated - my software setup below:
OS: Windows 10
Python version 3.13.9
pymc version 5.26.1
pytensor version 2.35.1

The solution seems to lie in in defining ndims_params for the Simulator class.
With the dummy model function the dimension issue disappears - and the SMC proceeds without errors.
This is the working code now

 sim_model = pm.Simulator('sim_model',
                                 pm_dummy,
                                 params=[all_sources,
                                        xyzdelta], 
                                  observed=sim_obsdata, 
                                  ndims_params=[2,2], # this is the new addition
                                  epsilon=1e-2)

However, in pymc 5.27.1 there is a FutureWarning: ndims_params is deprecated. Provide signature instead. message that’s raised, while in pymc 5.12.0 - there is no warning raised.

When not using the dummy model - there are new issues that arise - which probably needs a more detailed look.

Simulator assumes you have a scalar function by default. If you have a vector function, say like a MvNormal that has always a vector for the mean and a matrix for the covariance you need to specify the signature (old ndims_params): (p),(p,p)->(p) is the signature of multivariate normal.

The old equivalent was ndims_params=[1, 2]

You may want to check Distribution Dimensionality — PyMC 5.27.1 documentation

1 Like