class_docstr: An `Op` that produces a sample from a random variable.
  
  This is essentially `RandomFunction`, except that it removes the
  `outtype` dependency and handles shape dimension information more
  directly.
class_docstr_tok: ["An","`","Op","`","that","produces","a","sample","from","a","random","variable",".","This","is","essentially","`","RandomFunction","`",",","except","that","it","removes","the","`","outtype","`","dependency","and","handles","shape","dimension","information","more","directly","."]
docstr: Compute the output shape given the size and distribution parameters.
  
  Parameters
  ----------
  size
      The size parameter specified for this `RandomVariable`.
  dist_params
      The symbolic parameter for this `RandomVariable`'s distribution.
  param_shapes
      The shapes of the `dist_params` as given by `ShapeFeature`'s
      via `Op.infer_shape`'s `input_shapes` argument.  This parameter's
      values are essentially more accurate versions of ``[d.shape for d
      in dist_params]``.
docstr_tok: ["Compute","the","output","shape","given","the","size","and","distribution","parameters",".","Parameters","--","--","--","--","--","size","The","size","parameter","specified","for","this","`","RandomVariable","`",".","dist_params","The","symbolic","parameter","for","this","`","RandomVariable","`","'s","distribution",".","param_shapes","The","shapes","of","the","`","dist_params","`","as","given","by","`","ShapeFeature","`","'s","via","`","Op.infer_shape","`","'s","`","input_shapes","`","argument",".","This","parameter's","values","are","essentially","more","accurate","versions","of","``","[","d.shape","for","d","in","dist_params","]","``","."]
code: def _infer_shape(
      self,
      size: TensorVariable,
      dist_params: Sequence[TensorVariable],
      param_shapes: Optional[Sequence[tuple[Variable, ...]]] = None,
  ) -> Union[TensorVariable, tuple[ScalarVariable, ...]]:
      """Compute the output shape given the size and distribution parameters.
  
      Parameters
      ----------
      size
          The size parameter specified for this `RandomVariable`.
      dist_params
          The symbolic parameter for this `RandomVariable`'s distribution.
      param_shapes
          The shapes of the `dist_params` as given by `ShapeFeature`'s
          via `Op.infer_shape`'s `input_shapes` argument.  This parameter's
          values are essentially more accurate versions of ``[d.shape for d
          in dist_params]``.
  
      """
  
      from pytensor.tensor.extra_ops import broadcast_shape_iter
  
      if self.ndim_supp == 0:
          supp_shape = ()
      else:
          supp_shape = tuple(
              self._supp_shape_from_params(
                  dist_params, param_shapes=param_shapes
              )
          )
  
      size_len = get_vector_length(size)
  
      if size_len > 0:
          # Fail early when size is incompatible with parameters
          for i, (param, param_ndim_supp) in enumerate(
              zip(dist_params, self.ndims_params)
          ):
              param_batched_dims = (
                  getattr(param, "ndim", 0) - param_ndim_supp
              )
              if param_batched_dims > size_len:
                  raise ValueError(
                      f"Size length is incompatible with batched dimensions of parameter {i} {param}:\n"
                      f"len(size) = {size_len}, len(batched dims {param}) = {param_batched_dims}. "
                      f"Size length must be 0 or >= {param_batched_dims}"
                  )
  
          return tuple(size) + supp_shape
  
      # Size was not provided, we must infer it from the shape of the parameters
      if param_shapes is None:
          param_shapes = [shape_tuple(p) for p in dist_params]
  
      def extract_batch_shape(p, ps, n):
          shape = tuple(ps)
  
          if n == 0:
              return shape
  
          batch_shape = tuple(
              s if not b else constant(1, "int64")
              for s, b in zip(shape[:-n], p.type.broadcastable[:-n])
          )
          return batch_shape
  
      # These are versions of our actual parameters with the anticipated
      # dimensions (i.e. support dimensions) removed so that only the
      # independent variate dimensions are left.
      params_batch_shape = tuple(
          extract_batch_shape(p, ps, n)
          for p, ps, n in zip(
              dist_params, param_shapes, self.ndims_params
          )
      )
  
      if len(params_batch_shape) == 1:
          [batch_shape] = params_batch_shape
      elif len(params_batch_shape) > 1:
          # If there are multiple parameters, the dimensions of their
          # independent variates should broadcast together.
          batch_shape = broadcast_shape_iter(
              params_batch_shape,
              arrays_are_shapes=True,
          )
      else:
          # Distribution has no parameters
          batch_shape = ()
  
      shape = batch_shape + supp_shape
  
      if not shape:
          shape = constant([], dtype="int64")
  
      return shape
  
imports: from collections.abc import Sequence
  from copy import copy
  from typing import Optional, Union
  import numpy
  import pytensor
  from pytensor.configdefaults import config
  from pytensor.graph.basic import Apply, Variable, equal_computations
  from pytensor.graph.op import Op
  from pytensor.graph.replace import _vectorize_node
  from pytensor.misc.safe_asarray import _asarray
  from pytensor.scalar import ScalarVariable
  from pytensor.tensor.basic import as_tensor_variable, concatenate, constant, get_underlying_scalar_constant_value, get_vector_length, infer_static_shape
  from pytensor.tensor.random.type import RandomGeneratorType, RandomStateType, RandomType
  from pytensor.tensor.random.utils import broadcast_params, normalize_size_param
  from pytensor.tensor.shape import shape_tuple
  from pytensor.tensor.type import TensorType, all_dtypes
  from pytensor.tensor.type_other import NoneConst
  from pytensor.tensor.variable import TensorVariable
label_desc: Use image node_id 5 for calling the RandomVariable obj's underlying member method code with example usage: obj._infer_shape(size, dist_params, param_shapes) and returns: shape, unknown, batch_shape, shape