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