1+ # Copyright 2020 The TensorFlow Quantum Authors. All Rights Reserved.
2+ #
3+ # Licensed under the Apache License, Version 2.0 (the "License");
4+ # you may not use this file except in compliance with the License.
5+ # You may obtain a copy of the License at
6+ #
7+ # http://www.apache.org/licenses/LICENSE-2.0
8+ #
9+ # Unless required by applicable law or agreed to in writing, software
10+ # distributed under the License is distributed on an "AS IS" BASIS,
11+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ # See the License for the specific language governing permissions and
13+ # limitations under the License.
14+ # ==============================================================================
15+ """Module for high performance noisy circuit sampling ops"""
16+ import os
17+ import tensorflow as tf
18+ from tensorflow_quantum .core .ops import tfq_utility_ops
19+ from tensorflow_quantum .core .ops .load_module import load_module
20+
21+ NOISY_OP_MODULE = load_module (os .path .join ("noise" , "_tfq_noise_ops.so" ))
22+
23+
24+ def samples (programs , symbol_names , symbol_values , num_samples ):
25+ """Generate samples using the C++ noisy trajectory simulator.
26+
27+ Simulate the final state of `programs` given `symbol_values` are placed
28+ inside of the symbols with the name in `symbol_names` in each circuit.
29+ Channels in this simulation will be "tossed" to a certain realization
30+ during simulation. After each simulation is a run a single bitstring
31+ will be drawn. These simulations are repeated `num_samples` times.
32+
33+
34+ >>> # Sample a noisy circuit with C++.
35+ >>> qubit = cirq.GridQubit(0, 0)
36+ >>> my_symbol = sympy.Symbol('alpha')
37+ >>> my_circuit_tensor = tfq.convert_to_tensor([
38+ ... cirq.Circuit(
39+ ... cirq.X(qubit) ** my_symbol,
40+ ... cirq.depolarize(0.01)(qubit)
41+ ... )
42+ ... ])
43+ >>> my_values = np.array([[0.123]])
44+ >>> my_num_samples = np.array([100])
45+ >>> # This op can now be run with:
46+ >>> output = tfq.noise.samples(
47+ ... my_circuit_tensor, ['alpha'], my_values, my_num_samples)
48+ >>> output
49+ <tf.RaggedTensor [[[0], [0], [1], [0], [0], [0], [0], [1], [0], [0]]]>
50+
51+
52+ Args:
53+ programs: `tf.Tensor` of strings with shape [batch_size] containing
54+ the string representations of the circuits to be executed.
55+ symbol_names: `tf.Tensor` of strings with shape [n_params], which
56+ is used to specify the order in which the values in
57+ `symbol_values` should be placed inside of the circuits in
58+ `programs`.
59+ symbol_values: `tf.Tensor` of real numbers with shape
60+ [batch_size, n_params] specifying parameter values to resolve
61+ into the circuits specified by programs, following the ordering
62+ dictated by `symbol_names`.
63+ num_samples: `tf.Tensor` with one element indicating the number of
64+ samples to draw for all circuits in the batch.
65+ Returns:
66+ A `tf.Tensor` containing the samples taken from each circuit in
67+ `programs`.
68+ """
69+ padded_samples = NOISY_OP_MODULE .tfq_noisy_samples (
70+ programs , symbol_names , tf .cast (symbol_values , tf .float32 ), num_samples )
71+ return tfq_utility_ops .padded_to_ragged (padded_samples )
0 commit comments