def test_padded_to_ragged(self, padded_array): """Test for padded_to_ragged utility.""" mask = np.where(np.array(padded_array) > -1, True, False) expected = tf.ragged.boolean_mask(padded_array, mask) actual = tfq_utility_ops.padded_to_ragged( np.array(padded_array, dtype=float)) self.assertAllEqual(expected, actual)
def samples(programs, symbol_names, symbol_values, num_samples): """Generate samples using the C++ noisy trajectory simulator. Simulate the final state of `programs` given `symbol_values` are placed inside of the symbols with the name in `symbol_names` in each circuit. Channels in this simulation will be "tossed" to a certain realization during simulation. After each simulation is a run a single bitstring will be drawn. These simulations are repeated `num_samples` times. >>> # Sample a noisy circuit with C++. >>> qubit = cirq.GridQubit(0, 0) >>> my_symbol = sympy.Symbol('alpha') >>> my_circuit_tensor = tfq.convert_to_tensor([ ... cirq.Circuit( ... cirq.X(qubit) ** my_symbol, ... cirq.depolarize(0.01)(qubit) ... ) ... ]) >>> my_values = np.array([[0.123]]) >>> my_num_samples = np.array([100]) >>> # This op can now be run with: >>> output = tfq.noise.samples( ... my_circuit_tensor, ['alpha'], my_values, my_num_samples) >>> output <tf.RaggedTensor [[[0], [0], [1], [0], [0], [0], [0], [1], [0], [0]]]> Args: programs: `tf.Tensor` of strings with shape [batch_size] containing the string representations of the circuits to be executed. symbol_names: `tf.Tensor` of strings with shape [n_params], which is used to specify the order in which the values in `symbol_values` should be placed inside of the circuits in `programs`. symbol_values: `tf.Tensor` of real numbers with shape [batch_size, n_params] specifying parameter values to resolve into the circuits specified by programs, following the ordering dictated by `symbol_names`. num_samples: `tf.Tensor` with one element indicating the number of samples to draw for all circuits in the batch. Returns: A `tf.Tensor` containing the samples taken from each circuit in `programs`. """ padded_samples = NOISY_OP_MODULE.tfq_noisy_samples( programs, symbol_names, tf.cast(symbol_values, tf.float32), num_samples) return tfq_utility_ops.padded_to_ragged(padded_samples)
def get_state_op(backend=None): """Get a TensorFlow op that produces states from given quantum circuits. This function produces a non-differentiable op that will calculate batches of state tensors given tensor batches of `cirq.Circuit`s and parameter values. >>> # Simulate circuits with cirq. >>> my_op = tfq.get_state_op(backend=cirq.DensityMatrixSimulator()) >>> # Simulate circuits with C++. >>> my_second_op = tfq.get_state_op() >>> # Prepare some inputs. >>> qubit = cirq.GridQubit(0, 0) >>> my_symbol = sympy.Symbol('alpha') >>> my_circuit_tensor = tfq.convert_to_tensor([ ... cirq.Circuit(cirq.Y(qubit) ** my_symbol) ... ]) >>> my_values = np.array([[0.5]]) >>> # This op can now be run to calculate the state. >>> output = my_second_op(my_circuit_tensor, ['alpha'], my_values) >>> output <tf.RaggedTensor [[(0.5+0.5j), (0.5+0.5j)]]> Args: backend: Optional Python `object` that specifies what backend this op should use when evaluating circuits. Can be any `cirq.SimulatesFinalState`. If not provided, the default C++ wavefunction simulator will be used. Returns: A `callable` with the following signature: ```op(programs, symbol_names, symbol_values)``` programs: `tf.Tensor` of strings with shape [batch_size] containing the string representations of the circuits to be executed. symbol_names: `tf.Tensor` of strings with shape [n_params], which is used to specify the order in which the values in `symbol_values` should be placed inside of the circuits in `programs`. symbol_values: `tf.Tensor` of real numbers with shape [batch_size, n_params] specifying parameter values to resolve into the circuits specified by programs, following the ordering dictated by `symbol_names`. Returns: `tf.Tensor` with shape [batch_size, <ragged> size of state] that contains the state information of the circuit. """ # TODO (mbbrough): investigate how the above docstring renders. if backend is None: return lambda programs, symbol_names, symbol_values: \ tfq_utility_ops.padded_to_ragged(TFQWavefunctionSimulator.state( programs, symbol_names, symbol_values)) if isinstance(backend, (cirq.SimulatesFinalState)): return lambda programs, symbol_names, symbol_values: \ tfq_utility_ops.padded_to_ragged( cirq_ops._get_cirq_simulate_state(backend)( programs, symbol_names, symbol_values)) raise TypeError("Backend {} is invalid. Expected a Cirq.SimulatesFinalState" " or None.".format(backend))
def get_sampling_op(backend=None): """Get a Tensorflow op that produces samples from given quantum circuits. This function produces a non-differentiable op that will calculate batches of circuit samples given tensor batches of `cirq.Circuit`s, parameter values, and a scalar telling the op how many samples to take. >>> # Simulate circuits with cirq. >>> my_op = tfq.get_sampling_op(backend=cirq.sim.Simulator()) >>> # Simulate circuits with C++. >>> my_second_op = tfq.get_sampling_op() >>> # Prepare some inputs. >>> qubit = cirq.GridQubit(0, 0) >>> my_symbol = sympy.Symbol('alpha') >>> my_circuit_tensor = tfq.convert_to_tensor( ... [cirq.Circuit(cirq.X(qubit)**my_symbol)]) >>> my_values = np.array([[2.0]]) >>> n_samples = np.array([10]) >>> # This op can now be run to take samples. >>> output = my_second_op( ... my_circuit_tensor, ['alpha'], my_values, n_samples) >>> output <tf.RaggedTensor [[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]]> Args: backend: Optional Python `object` that specifies what backend this op should use when evaluating circuits. Can be any `cirq.Sampler`. If not provided the default C++ sampling op is returned. Returns: A `callable` with the following signature: ```op(programs, symbol_names, symbol_values, num_samples)``` programs: `tf.Tensor` of strings with shape [batch_size] containing the string representations of the circuits to be executed. symbol_names: `tf.Tensor` of strings with shape [n_params], which is used to specify the order in which the values in `symbol_values` should be placed inside of the circuits in `programs`. symbol_values: `tf.Tensor` of real numbers with shape [batch_size, n_params] specifying parameter values to resolve into the circuits specified by programs, following the ordering dictated by `symbol_names`. num_samples: `tf.Tensor` with one element indicating the number of samples to draw. Returns: `tf.Tensor` with shape [batch_size, num_samples, <ragged> n_qubits] that holds samples (as boolean values) for each circuit. """ # TODO (mbbrough): investigate how the above docstring renders. if backend is None: return lambda programs, symbol_names, symbol_values, num_samples: \ tfq_utility_ops.padded_to_ragged(TFQWavefunctionSimulator.samples( programs, symbol_names, symbol_values, num_samples)) if isinstance(backend, (cirq.SimulatesSamples, cirq.Sampler)): return lambda programs, symbol_names, symbol_values, num_samples: \ tfq_utility_ops.padded_to_ragged(cirq_ops._get_cirq_samples(backend)( programs, symbol_names, symbol_values, num_samples)) raise TypeError("Backend {} is invalid. Expected a Cirq.Sampler " "or None.".format(backend))
def get_state_op( backend=None, *, quantum_concurrent=quantum_context.get_quantum_concurrent_op_mode()): """Get a TensorFlow op that produces states from given quantum circuits. This function produces a non-differentiable op that will calculate batches of state tensors given tensor batches of `cirq.Circuit`s and parameter values. >>> # Simulate circuits with cirq. >>> my_op = tfq.get_state_op(backend=cirq.DensityMatrixSimulator()) >>> # Simulate circuits with C++. >>> my_second_op = tfq.get_state_op() >>> # Prepare some inputs. >>> qubit = cirq.GridQubit(0, 0) >>> my_symbol = sympy.Symbol('alpha') >>> my_circuit_tensor = tfq.convert_to_tensor([ ... cirq.Circuit(cirq.Y(qubit) ** my_symbol) ... ]) >>> my_values = np.array([[0.5]]) >>> # This op can now be run to calculate the state. >>> output = my_second_op(my_circuit_tensor, ['alpha'], my_values) >>> output <tf.RaggedTensor [[(0.5+0.5j), (0.5+0.5j)]]> Args: backend: Optional Python `object` that specifies what backend this op should use when evaluating circuits. Can be any `cirq.SimulatesFinalState`. If not provided, the default C++ wavefunction simulator will be used. quantum_concurrent: Optional Python `bool`. True indicates that the returned op should not block graph level parallelism on itself when executing. False indicates that graph level parallelism on itself should be blocked. Defaults to value specified in `tfq.get_quantum_concurrent_op_mode` which defaults to True (no blocking). This flag is only needed for advanced users when using TFQ for very large simulations, or when running on a real chip. Returns: A `callable` with the following signature: ```op(programs, symbol_names, symbol_values)``` programs: `tf.Tensor` of strings with shape [batch_size] containing the string representations of the circuits to be executed. symbol_names: `tf.Tensor` of strings with shape [n_params], which is used to specify the order in which the values in `symbol_values` should be placed inside of the circuits in `programs`. symbol_values: `tf.Tensor` of real numbers with shape [batch_size, n_params] specifying parameter values to resolve into the circuits specified by programs, following the ordering dictated by `symbol_names`. Returns: `tf.Tensor` with shape [batch_size, <ragged> size of state] that contains the state information of the circuit. """ # TODO (mbbrough): investigate how the above docstring renders. _check_quantum_concurrent(quantum_concurrent) op = None if backend is None: op = TFQWavefunctionSimulator.state if isinstance(backend, (cirq.SimulatesFinalState)): op = cirq_ops._get_cirq_simulate_state(backend) if op is not None: if quantum_concurrent is True: # Return an op that does not block graph level parallelism. return lambda programs, symbol_names, symbol_values: \ tfq_utility_ops.padded_to_ragged( op(programs, symbol_names, symbol_values)) # Return an op that does block graph level parallelism. return lambda programs, symbol_names, symbol_values: \ _GLOBAL_OP_LOCK.execute(lambda: tfq_utility_ops.padded_to_ragged( op(programs, symbol_names, symbol_values))) raise TypeError( "Backend {} is invalid. Expected a Cirq.SimulatesFinalState" " or None.".format(backend))