in tensorflow_quantum/python/layers/high_level/controlled_pqc.py [0:0]
def __init__(self,
model_circuit,
operators,
*,
repetitions=None,
backend='noiseless',
differentiator=None,
**kwargs):
"""Instantiate this layer.
Create a layer that will output expectation values of the given
operators when fed quantum data to it's input layer. This layer will
take two input tensors, one representing a quantum data source (these
circuits must not contain any symbols) and the other representing
control parameters for the model circuit that gets appended to the
datapoints.
model_circuit: `cirq.Circuit` containing `sympy.Symbols` that will be
used as the model which will be fed quantum data inputs.
operators: `cirq.PauliSum` or Python `list` of `cirq.PauliSum` objects
used as observables at the end of the model circuit.
repetitions: Optional Python `int` indicating how many samples to use
when estimating expectation values. If `None` analytic expectation
calculation is used.
backend: Optional Backend to use to simulate states. Defaults to
the noiseless TensorFlow simulator, however users may also
specify a preconfigured cirq simulation object to use instead.
If a cirq object is given it must inherit `cirq.Sampler` if
`sampled_based` is True or it must inherit
`cirq.sim.simulator.SimulatesExpectationValues` if `sample_based` is
False.
differentiator: Optional `tfq.differentiator` object to specify how
gradients of `model_circuit` should be calculated.
"""
super().__init__(**kwargs)
# Ingest model_circuit.
if not isinstance(model_circuit, cirq.Circuit):
raise TypeError("model_circuit must be a cirq.Circuit object."
" Given: ".format(model_circuit))
self._symbols_list = list(
sorted(util.get_circuit_symbols(model_circuit)))
self._symbols = tf.constant([str(x) for x in self._symbols_list])
self._circuit = util.convert_to_tensor([model_circuit])
if len(self._symbols_list) == 0:
raise ValueError("model_circuit has no sympy.Symbols. Please "
"provide a circuit that contains symbols so "
"that their values can be trained.")
# Ingest operators.
if isinstance(operators, (cirq.PauliString, cirq.PauliSum)):
operators = [operators]
if not isinstance(operators, (list, np.ndarray, tuple)):
raise TypeError("operators must be a cirq.PauliSum or "
"cirq.PauliString, or a list, tuple, "
"or np.array containing them. "
"Got {}.".format(type(operators)))
if not all([
isinstance(op, (cirq.PauliString, cirq.PauliSum))
for op in operators
]):
raise TypeError("Each element in operators to measure "
"must be a cirq.PauliString"
" or cirq.PauliSum")
self._operators = util.convert_to_tensor([operators])
# Ingest and promote repetitions.
self._analytic = False
if repetitions is None:
self._analytic = True
if not self._analytic and not isinstance(repetitions, numbers.Integral):
raise TypeError("repetitions must be a positive integer value."
" Given: ".format(repetitions))
if not self._analytic and repetitions <= 0:
raise ValueError("Repetitions must be greater than zero.")
if not self._analytic:
self._repetitions = tf.constant(
[[repetitions for _ in range(len(operators))]],
dtype=tf.dtypes.int32)
# Ingest backend and differentiator.
if backend == 'noisy':
raise ValueError("noisy backend value is not supported in "
"tfq.layers.ControlledPQC. Please use "
"tfq.layers.NoisyControlledPQC instead.")
not_default = backend != 'noiseless'
not_default &= backend is not None # legacy backend=None support.
if not isinstance(
backend,
cirq.Sampler) and repetitions is not None and not_default:
raise TypeError("provided backend does not inherit cirq.Sampler "
"and repetitions!=None. Please provide a backend "
"that inherits cirq.Sampler or set "
"repetitions=None.")
if not isinstance(backend, cirq.sim.simulator.SimulatesExpectationValues
) and repetitions is None and not_default:
raise TypeError("provided backend does not inherit "
"cirq.sim.simulator.SimulatesExpectationValues and "
"repetitions=None. Please provide a backend that "
"inherits "
"cirq.sim.simulator.SimulatesExpectationValues.")
if self._analytic:
self._layer = expectation.Expectation(backend=backend,
differentiator=differentiator)
else:
self._layer = sampled_expectation.SampledExpectation(
backend=backend, differentiator=differentiator)
self._append_layer = elementary.AddCircuit()