Beispiel #1
0
 def test_serialize_paulisum_invalid(self):
     """Ensure we don't support anything but GridQubits."""
     q0 = cirq.NamedQubit('wont work')
     a = 3.0 * cirq.Z(q0) - 2.0 * cirq.X(q0)
     with self.assertRaises(ValueError):
         serializer.serialize_paulisum(a)
Beispiel #2
0
 def test_serialize_paulisum_wrong_type(self, inp):
     """Attempt to serialize invalid object types."""
     with self.assertRaises(TypeError):
         serializer.serialize_paulisum(inp)
 def test_serialize_paulisum_simple(self, sum_proto_pair):
     """Ensure serialization is correct."""
     self.assertProtoEquals(
         sum_proto_pair[1],
         serializer.serialize_paulisum(sum_proto_pair[0]))
Beispiel #4
0
    def test_cirq_sampled_expectation_op_inputs(self):
        """test input checking in the state sim op."""
        test_op = cirq_ops._get_cirq_sampled_expectation(
            cirq.sim.sparse_simulator.Simulator())
        bits = cirq.GridQubit.rect(1, 5)
        test_circuit = serializer.serialize_circuit(
            cirq.testing.random_circuit(bits, MOMENT_DEPTH,
                                        0.9)).SerializeToString()
        test_pauli_sum = serializer.serialize_paulisum(
            cirq.PauliSum.from_pauli_strings([cirq.Z(bits[0])
                                              ])).SerializeToString()
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'symbol_names tensor must be of type string'):
            _ = test_op([test_circuit], [0], [[0]], [[test_pauli_sum]], [[1]])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'programs tensor must be of type string'):
            _ = test_op([0], ['rx'], [[0]], [test_pauli_sum], [[1]])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'real-valued numeric tensor.'):
            _ = test_op([test_circuit], ['rx'], 'junk', [[test_pauli_sum]],
                        [[1]])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'size of symbol_names tensor must match'):
            _ = test_op([test_circuit], ['rx'], [[1, 1]], [[test_pauli_sum]],
                        [[1]])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'size of symbol_names tensor must match'):
            _ = test_op([test_circuit], ['rx', 'ry'], [[1]],
                        [[test_pauli_sum]], [[1]])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'first dimension of symbol_values tensor'):
            _ = test_op([test_circuit, test_circuit], ['rx'], [[1]],
                        [test_pauli_sum], [[1]])
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'pauli_sums tensor must be of type string.'):
            _ = test_op([test_circuit], ['rx'], [[1]], 0, [[1]])
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'pauli_sums tensor must have the same batch shape'):
            _ = test_op([test_circuit], ['rx'], [[1]],
                        [[test_pauli_sum], [test_pauli_sum]], [[1]])
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'num_samples tensor must have the same shape'):
            _ = test_op([test_circuit], ['rx'], [[1]], [[test_pauli_sum]],
                        [[1], [1]])
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'num_samples tensor must be of type int32'):
            _ = test_op([test_circuit], ['rx'], [[1]], [[test_pauli_sum]],
                        [[1.0]])
        with self.assertRaisesRegex(
                tf.errors.InvalidArgumentError,
                'num_samples tensor must have the same shape'):
            _ = test_op([test_circuit], ['rx'], [[1]], [[test_pauli_sum]],
                        [[1], [1]])
        with self.assertRaisesRegex(tf.errors.InvalidArgumentError,
                                    'num_samples contains sample value <= 0'):
            _ = test_op([test_circuit], ['rx'], [[1]], [[test_pauli_sum]],
                        [[0]])

        _ = test_op([test_circuit], ['rx'], [[1]], [[test_pauli_sum]], [[1]])
        _ = test_op([test_circuit], [], [[]], [[test_pauli_sum]], [[1]])
Beispiel #5
0
def batch_calculate_sampled_expectation(circuits, param_resolvers, ops,
                                        n_samples, simulator):
    """Compute expectations from sampling circuits using parallel processing.

    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 simulator object
    (`cirq.DensityMatrixSimulator` and `cirq.Simulator` are currently supported)
    . 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.
        simulator: Simulator object. Currently supported are
            `cirq.DensityMatrixSimulator` and `cirq.Simulator`.

    Returns:
        `np.ndarray` containing the expectation values. Shape is:
            [len(circuits), len(ops[0])]
    """
    _validate_inputs(circuits, param_resolvers, simulator, 'sample')
    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)))

    return_mem_shape = (len(circuits), len(ops[0]))
    shared_array = _make_simple_view(return_mem_shape, -2, np.float32, 'f')

    # avoid mutating ops array
    ops = np.copy(ops)
    # TODO (mbbrough): make cirq PauliSums pickable at some point ?
    for i in range(len(ops)):
        for j in range(len(ops[i])):
            ops[i][j] = serializer.serialize_paulisum(ops[i][j])

    input_args = list(
        _prep_pool_input_args(list(
            itertools.product(range(len(circuits)), range(len(ops[0])))),
                              circuits,
                              param_resolvers,
                              ops,
                              n_samples,
                              slice_args=False))

    with pathos.pools._ProcessPool(processes=None,
                                   initializer=_setup_dict,
                                   initargs=(shared_array, return_mem_shape,
                                             simulator, None)) as pool:

        pool.starmap(_sample_expectation_worker_func, input_args)

    return _convert_simple_view_to_result(shared_array, np.float32,
                                          return_mem_shape)
Beispiel #6
0
def batch_calculate_expectation(circuits, param_resolvers, ops, simulator):
    """Compute expectations from circuits using parallel processing.

    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 calculations will be carried out using the simulator object
    (`cirq.DensityMatrixSimulator` and `cirq.Simulator` are currently supported)

    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.
        simulator: Simulator object. Currently supported are
            `cirq.DensityMatrixSimulator` and `cirq.Simulator`.

    Returns:
        `np.ndarray` containing the expectation values. Shape is:
            [len(circuits), len(ops[0])]
    """
    _validate_inputs(circuits, param_resolvers, simulator, 'analytic')
    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.')

    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)))

    return_mem_shape = (len(circuits), len(ops[0]))
    if isinstance(simulator,
                  cirq.sim.density_matrix_simulator.DensityMatrixSimulator):
        post_process = lambda op, state, order: sum(
            x._expectation_from_density_matrix_no_validation(
                state.final_density_matrix, order) for x in op).real
    elif isinstance(simulator, cirq.sim.sparse_simulator.Simulator):
        post_process = \
            lambda op, state, order: op.expectation_from_wavefunction(
                state.final_state, order).real
    else:
        raise TypeError('Simulator {} is not supported by '
                        'batch_calculate_expectation.'.format(type(simulator)))

    shared_array = _make_simple_view(return_mem_shape, -2, np.float32, 'f')

    # avoid mutating ops array
    ops = np.copy(ops)
    # TODO (mbbrough): make cirq PauliSUms pickable at some point ?
    for i in range(len(ops)):
        for j in range(len(ops[i])):
            ops[i][j] = serializer.serialize_paulisum(ops[i][j])

    input_args = list(
        _prep_pool_input_args(list(
            itertools.product(range(len(circuits)), range(len(ops[0])))),
                              circuits,
                              param_resolvers,
                              ops,
                              slice_args=False))

    with pathos.pools._ProcessPool(processes=None,
                                   initializer=_setup_dict,
                                   initargs=(shared_array, return_mem_shape,
                                             simulator, post_process)) as pool:

        pool.starmap(_analytical_expectation_worker_func, input_args)

    return _convert_simple_view_to_result(shared_array, np.float32,
                                          return_mem_shape)