def batch_calculate_sampled_expectation()

in tensorflow_quantum/core/ops/batch_util.py [0:0]


def batch_calculate_sampled_expectation(circuits, param_resolvers, ops,
                                        n_samples, sampler):
    """Compute expectations from sampling a batch of circuits.

    Returns a `np.ndarray` containing the expectation values of `ops`
    applied to a specific circuit in `circuits`, given that the
    corresponding `cirq.ParamResolver` in `param_resolvers` was used to resolve
    any symbols in the circuit. Specifically the returned array at index `i,j`
    will be equal to the expectation value of `ops[i][j]` on `circuits[i]` with
    `param_resolvers[i]` used to resolve any symbols in `circuits[i]`.
    Expectation estimations will be carried out using the sampler object.
    Expectations for ops[i][j] are estimated by drawing n_samples[i][j]
    samples.

    Args:
        circuits: Python `list` of `cirq.Circuit`s.
        param_resolvers: Python `list` of `cirq.ParamResolver`s, where
            `param_resolvers[i]` is the resolver to be used with `circuits[i]`.
        ops: 2d Python `list` of `cirq.PauliSum` objects where `ops[i][j]` will
            be used to calculate the expectation on `circuits[i]` for all `j`,
            after `param_resolver[i]` is used to resolve any parameters
            in the circuit.
        n_samples: 2d Python `list` of `int`s where `n_samples[i][j]` is
            equal to the number of samples to draw in each term of `ops[i][j]`
            when estimating the expectation.
        sampler: Anything inheriting `cirq.Sampler`.

    Returns:
        `np.ndarray` containing the expectation values. Shape is:
            [len(circuits), len(ops[0])]
    """
    _validate_inputs(circuits, param_resolvers, sampler, 'sample')
    if _check_empty(circuits):
        return np.zeros((0, 0), dtype=np.float32)

    if not isinstance(ops, (list, tuple, np.ndarray)):
        raise TypeError('ops must be a list or array.'
                        ' Given: {}'.format(type(ops)))

    if len(ops) != len(circuits):
        raise ValueError('Shape of ops and circuits do not match.')

    if len(n_samples) != len(circuits):
        raise ValueError('Shape of n_samples does not match circuits.')

    for sub_list in n_samples:
        if not isinstance(sub_list, (list, tuple, np.ndarray)):
            raise TypeError('Elements of n_elements must be lists of ints.')
        for x in sub_list:
            if not isinstance(x, int):
                raise TypeError('Non-integer value found in n_samples.')
            if x <= 0:
                raise ValueError('n_samples contains sample value <= 0.')

    for sub_list in ops:
        if not isinstance(sub_list, (list, tuple, np.ndarray)):
            raise TypeError('elements of ops must be type list.')
        for x in sub_list:
            if not isinstance(x, cirq.PauliSum):
                raise TypeError('ops must contain only cirq.PauliSum objects.'
                                ' Given: {}'.format(type(x)))

    all_exp_vals = np.full((len(circuits), len(ops[0])), -2, dtype=np.float32)

    for c_index, (c, params) in enumerate(zip(circuits, param_resolvers)):
        # (#679) Just ignore empty programs.
        if len(c.all_qubits()) == 0:
            continue
        circuit = cirq.resolve_parameters(c, params)
        for op_index, op in enumerate(ops[c_index]):
            collector = TFQPauliSumCollector(
                circuit, op, samples_per_term=n_samples[c_index][op_index])
            collector.collect(sampler)
            result = collector.estimated_energy().real
            all_exp_vals[c_index][op_index] = result

    return all_exp_vals