code: def mutually_broadcastable_shapes(
      *,
      num_shapes: Union[UniqueIdentifier, int] = not_set,
      signature: Union[UniqueIdentifier, str] = not_set,
      base_shape: Shape = (),
      min_dims: int = 0,
      max_dims: Optional[int] = None,
      min_side: int = 1,
      max_side: Optional[int] = None,
  ) -> st.SearchStrategy[BroadcastableShapes]:
      """Return a strategy for a specified number of shapes N that are
      mutually-broadcastable with one another and with the provided base shape.
  
      * ``num_shapes`` is the number of mutually broadcast-compatible shapes to generate.
      * ``base_shape`` is the shape against which all generated shapes can broadcast.
        The default shape is empty, which corresponds to a scalar and thus does
        not constrain broadcasting at all.
      * ``min_dims`` is the smallest length that the generated shape can possess.
      * ``max_dims`` is the largest length that the generated shape can possess,
        defaulting to ``max(len(shape), min_dims) + 2``.
      * ``min_side`` is the smallest size that an unaligned dimension can possess.
      * ``max_side`` is the largest size that an unaligned dimension can possess,
        defaulting to 2 plus the size of the largest aligned dimension.
  
      The strategy will generate a :obj:`python:typing.NamedTuple` containing:
  
      * ``input_shapes`` as a tuple of the N generated shapes.
      * ``result_shape`` as the resulting shape produced by broadcasting the N shapes
        with the base shape.
  
      The following are some examples drawn from this strategy.
  
      .. code-block:: pycon
  
          >>> # Draw three shapes where each shape is broadcast-compatible with (2, 3)
          ... strat = mutually_broadcastable_shapes(num_shapes=3, base_shape=(2, 3))
          >>> for _ in range(5):
          ...     print(strat.example())
          BroadcastableShapes(input_shapes=((4, 1, 3), (4, 2, 3), ()), result_shape=(4, 2, 3))
          BroadcastableShapes(input_shapes=((3,), (1, 3), (2, 3)), result_shape=(2, 3))
          BroadcastableShapes(input_shapes=((), (), ()), result_shape=())
          BroadcastableShapes(input_shapes=((3,), (), (3,)), result_shape=(3,))
          BroadcastableShapes(input_shapes=((1, 2, 3), (3,), ()), result_shape=(1, 2, 3))
  
      """
      arg_msg = "Pass either the `num_shapes` or the `signature` argument, but not both."
      if num_shapes is not not_set:
          check_argument(signature is not_set, arg_msg)
          check_type(int, num_shapes, "num_shapes")
          assert isinstance(num_shapes, int)  # for mypy
          parsed_signature = None
          sig_dims = 0
      else:
          check_argument(signature is not not_set, arg_msg)
          if signature is None:
              raise InvalidArgument(
                  "Expected a string, but got invalid signature=None.  "
                  "(maybe .signature attribute of an element-wise ufunc?)"
              )
          check_type(str, signature, "signature")
          parsed_signature = _hypothesis_parse_gufunc_signature(
              signature
          )
          all_shapes = (
              *parsed_signature.input_shapes,
              parsed_signature.result_shape,
          )
          sig_dims = min(len(s) for s in all_shapes)
          num_shapes = len(parsed_signature.input_shapes)
  
      if num_shapes < 1:
          raise InvalidArgument(
              f"num_shapes={num_shapes} must be at least 1"
          )
  
      check_type(tuple, base_shape, "base_shape")
      check_type(int, min_side, "min_side")
      check_type(int, min_dims, "min_dims")
      check_valid_dims(min_dims, "min_dims")
  
      strict_check = max_dims is not None
  
      if max_dims is None:
          max_dims = min(
              max(len(base_shape), min_dims) + 2, NDIM_MAX - sig_dims
          )
      check_type(int, max_dims, "max_dims")
      check_valid_dims(max_dims, "max_dims")
  
      if max_side is None:
          max_side = max(base_shape[-max_dims:] + (min_side,)) + 2
      check_type(int, max_side, "max_side")
  
      order_check("dims", 0, min_dims, max_dims)
      order_check("side", 0, min_side, max_side)
  
      if signature is not None and max_dims > NDIM_MAX - sig_dims:
          raise InvalidArgument(
              f"max_dims={signature!r} would exceed the {NDIM_MAX}-dimension"
              "limit Hypothesis imposes on array shapes, "
              f"given signature={parsed_signature!r}"
          )
  
      if strict_check:
          dims = max_dims
          bound_name = "max_dims"
      else:
          dims = min_dims
          bound_name = "min_dims"
  
      # check for unsatisfiable min_side
      if not all(
          min_side <= s for s in base_shape[::-1][:dims] if s != 1
      ):
          raise InvalidArgument(
              f"Given base_shape={base_shape}, there are no broadcast-compatible "
              f"shapes that satisfy: {bound_name}={dims} and min_side={min_side}"
          )
  
      # check for unsatisfiable [min_side, max_side]
      if not (
          min_side <= 1 <= max_side
          or all(s <= max_side for s in base_shape[::-1][:dims])
      ):
          raise InvalidArgument(
              f"Given base_shape={base_shape}, there are no broadcast-compatible "
              f"shapes that satisfy all of {bound_name}={dims}, "
              f"min_side={min_side}, and max_side={max_side}"
          )
  
      if not strict_check:
          # reduce max_dims to exclude unsatisfiable dimensions
          for n, s in zip(range(max_dims), base_shape[::-1]):
              if s < min_side and s != 1:
                  max_dims = n
                  break
              elif not (min_side <= 1 <= max_side or s <= max_side):
                  max_dims = n
                  break
  
      return MutuallyBroadcastableShapesStrategy(
          num_shapes=num_shapes,
          signature=parsed_signature,
          base_shape=base_shape,
          min_dims=min_dims,
          max_dims=max_dims,
          min_side=min_side,
          max_side=max_side,
      )
  
imports: import re
  from typing import NamedTuple, Optional, Tuple, Union
  from hypothesis import assume, strategies
  from hypothesis.errors import InvalidArgument
  from hypothesis.internal.conjecture.utils import _calc_p_continue
  from hypothesis.internal.coverage import check_function
  from hypothesis.internal.validation import check_type, check_valid_interval
  from hypothesis.strategies._internal.utils import defines_strategy
  from hypothesis.utils.conventions import UniqueIdentifier, not_set
label_desc: Use image node_id 8 for calling a global function with example usage: mutually_broadcastable_shapes() and returns: MutuallyBroadcastableShapesStrategy