@hps.composite<EOL>def broadcasting_shapes(draw, target_shape, n):
target_shape = tf.TensorShape(target_shape)<EOL>target_rank = target_shape.ndims<EOL>result = []<EOL>current_shape = tf.TensorShape([])<EOL>for is_last in [False] * (n-<NUM_LIT:1>) + [True]:<EOL><INDENT>next_rank, force_fullsize_dim = _compute_rank_and_fullsize_reqd(<EOL>draw, target_shape, current_shape, is_last=is_last)<EOL>next_shape = target_shape[target_rank - next_rank:].as_list()<EOL>for i, force_fullsize in enumerate(force_fullsize_dim):<EOL><INDENT>if not force_fullsize and draw(hps.booleans()):<EOL><INDENT>next_shape[i] = <NUM_LIT:1><EOL><DEDENT><DEDENT>next_shape = tf.TensorShape(next_shape)<EOL>current_shape = tf.broadcast_static_shape(current_shape, next_shape)<EOL>result.append(next_shape)<EOL><DEDENT>return result<EOL>
Draws a set of `n` shapes that broadcast to `target_shape`.

    For each shape we need to choose its rank, and whether or not each axis i is 1
    or target_shape[i]. This function chooses a set of `n` shapes that have
    possibly mismatched ranks, and possibly broadcasting axes, with the promise
    that the broadcast of the set of all shapes matches `target_shape`.

    Args:
      draw: Hypothesis sampler.
      target_shape: The target (fully-defined) batch shape.
      n: `int`, the number of shapes to draw.

    Returns:
      shapes: Sequence of `tf.TensorShape` such that the set of shapes broadcast
        to `target_shape`. The shapes are fully defined.