<br />

|---|
| [![](https://www.tensorflow.org/images/GitHub-Mark-32px.png) View source on GitHub](https://github.com/tensorflow/quantum/blob/v0.7.6/tensorflow_quantum/python/layers/high_level/pqc.py#L28-L356) |

Parametrized Quantum Circuit (PQC) Layer.

    tfq.layers.PQC(
        model_circuit,
        operators,
        *,
        repetitions=None,
        backend='noiseless',
        differentiator=None,
        initializer=tf.keras.initializers.RandomUniform(0, 2 * np.pi),
        regularizer=None,
        constraint=None,
        **kwargs
    )

### Used in the notebooks

| Used in the tutorials |
|---|
| - [Quantum Convolutional Neural Network](https://www.tensorflow.org/quantum/tutorials/qcnn) - [MNIST classification](https://www.tensorflow.org/quantum/tutorials/mnist) - [Noise](https://www.tensorflow.org/quantum/tutorials/noise) |

<br />

<br />

<br />

| ## Args ||
|---|---|
| `model_circuit` | [`cirq.Circuit`](https://quantumai.google/reference/python/cirq/Circuit) <br /> Circuit with sympy.Symbols to be trained. |
| `operators` | `Union[cirq.PauliSum, cirq.PauliString, list]` <br /> Observable(s) to measure. |
| `repetitions` | `Optional[int]` <br /> Number of measurement repetitions. If None, analytic expectation is used. backend (Union\[str, cirq.Sampler, cirq.sim.simulator.SimulatesExpectationValues\]): Backend simulator. |
| `differentiator` | `Optional[tfq.differentiators.Differentiator]` <br /> Differentiation scheme. |
| `initializer` | [`tf.keras.initializers.Initializer`](https://www.tensorflow.org/api_docs/python/tf/keras/Initializer) <br /> Initializer for circuit parameters. |
| `regularizer` | `Optional[tf.keras.regularizers.Regularizer]` <br /> Regularizer for circuit parameters. |
| `constraint` | `Optional[tf.keras.constraints.Constraint]` <br /> Constraint for circuit parameters. |
| `**kwargs` | Additional keyword arguments for the parent class. |

<br />

<br />

<br />

<br />

| ## Input shape ||
|---|---|
| tf.Tensor of shape \[batch_size\], each entry a serialized circuit (from tfq.convert_to_tensor). ||

<br />

<br />

<br />

<br />

| ## Output shape ||
|---|---|
| tf.Tensor of shape \[batch_size, n_operators\], expectation values for each operator. ||

<br />

This layer is for training parameterized quantum models.
Given a parameterized circuit, this layer initializes the parameters
and manages them in a Keras native way.

We start by defining a simple quantum circuit on one qubit.
This circuit parameterizes an arbitrary rotation on the Bloch sphere in
terms of the three angles a, b, and c:

    q = cirq.GridQubit(0, 0)
    (a, b, c) = sympy.symbols("a b c")
    circuit = cirq.Circuit(
        cirq.rz(a)(q),
        cirq.rx(b)(q),
        cirq.rz(c)(q),
        cirq.rx(-b)(q),
        cirq.rz(-a)(q)
    )

In order to extract information from our circuit, we must apply measurement
operators. For now we choose to make a Z measurement. In order to observe
an output, we must also feed our model quantum data (NOTE: quantum data
means quantum circuits with no free parameters). Though the output values
will depend on the default random initialization of the angles in our model,
one will be the negative of the other since [`cirq.X(q)`](https://quantumai.google/reference/python/cirq/X) causes a bit flip:

    outputs = tfq.layers.PQC(circuit, cirq.Z(q))
    quantum_data = tfq.convert_to_tensor([
        cirq.Circuit(),
        cirq.Circuit(cirq.X(q))
    ])
    res = outputs(quantum_data)
    res
    <tf.Tensor: id=577, shape=(2, 1), dtype=float32, numpy=
    array([[ 0.8722095],
           [-0.8722095]], dtype=float32)>

We can also choose to measure the three pauli matrices, sufficient to
fully characterize the operation of our model, or choose to simulate
sampled expectation values by specifying a number of measurement shots
(repetitions) to average over. Notice that using only 200 repetitions
introduces variation between the two rows of data, due to the
probabilistic nature of measurement.

    measurement = [cirq.X(q), cirq.Y(q), cirq.Z(q)]
    outputs = tfq.layers.PQC(circuit, measurement, repetitions=200)
    quantum_data = tfq.convert_to_tensor([
        cirq.Circuit(),
        cirq.Circuit(cirq.X(q))
    ])
    res = outputs(quantum_data)
    res
    <tf.Tensor: id=808, shape=(2, 3), dtype=float32, numpy=
    array([[-0.38,  0.9 ,  0.14],
           [ 0.19, -0.95, -0.35]], dtype=float32)>

A value for `backend` can also be supplied in the layer constructor
arguments to indicate which supported backend you would like to use.
A value for `differentiator` can also be supplied in the constructor
to indicate the differentiation scheme this `PQC` layer should use.
Here's how you would take the gradients of the above example using a
[`cirq.Simulator`](https://quantumai.google/reference/python/cirq/Simulator) backend (which is slower than the default
`backend='noiseless'` which uses C++):

    q = cirq.GridQubit(0, 0)
    (a, b, c) = sympy.symbols("a b c")
    circuit = cirq.Circuit(
        cirq.rz(a)(q),
        cirq.rx(b)(q),
        cirq.rz(c)(q),
        cirq.rx(-b)(q),
        cirq.rz(-a)(q)
    )
    measurement = [cirq.X(q), cirq.Y(q), cirq.Z(q)]
    outputs = tfq.layers.PQC(
        circuit,
        measurement,
        repetitions=5000,
        backend=cirq.Simulator(),
        differentiator=tfq.differentiators.ParameterShift())
    quantum_data = tfq.convert_to_tensor([
        cirq.Circuit(),
        cirq.Circuit(cirq.X(q))
    ])
    res = outputs(quantum_data)
    res
    <tf.Tensor: id=891, shape=(2, 3), dtype=float32, numpy=
    array([[-0.5956, -0.2152,  0.7756],
           [ 0.5728,  0.1944, -0.7848]], dtype=float32)>

Lastly, like all layers in TensorFlow the `PQC` layer can be called on any
[`tf.Tensor`](https://www.tensorflow.org/api_docs/python/tf/Tensor) as long as it is the right shape. This means you could replace
replace `quantum_data` with values fed in from a [`tf.keras.Input`](https://www.tensorflow.org/api_docs/python/tf/keras/Input).

<br />

<br />

<br />

| ## Attributes ||
|---|---|
| `compute_dtype` | The dtype of the computations performed by the layer. |
| `dtype` | Alias of `layer.variable_dtype`. |
| `dtype_policy` | <br /> <br /> |
| `input` | Retrieves the input tensor(s) of a symbolic operation. <br /> Only returns the tensor(s) corresponding to the *first time* the operation was called. |
| `input_dtype` | The dtype layer inputs should be converted to. |
| `input_spec` | <br /> <br /> |
| `losses` | List of scalar losses from `add_loss`, regularizers and sublayers. |
| `metrics` | List of all metrics. |
| `metrics_variables` | List of all metric variables. |
| `non_trainable_variables` | List of all non-trainable layer state. <br /> This extends `layer.non_trainable_weights` to include all state used by the layer including state for metrics and `SeedGenerator`s. |
| `non_trainable_weights` | List of all non-trainable weight variables of the layer. <br /> These are the weights that should not be updated by the optimizer during training. Unlike, `layer.non_trainable_variables` this excludes metric state and random seeds. |
| `output` | Retrieves the output tensor(s) of a layer. <br /> Only returns the tensor(s) corresponding to the *first time* the operation was called. |
| `path` | The path of the layer. <br /> If the layer has not been built yet, it will be `None`. |
| `quantization_mode` | The quantization mode of this layer, `None` if not quantized. |
| `supports_masking` | Whether this layer supports computing a mask using `compute_mask`. |
| `symbols` | The symbols that are managed by this layer (in-order). <br /> > [!NOTE] > **Note:** `symbols[i]` indicates what symbol name the managed variables in this layer map to. |
| `trainable` | Settable boolean, whether this layer should be trainable or not. |
| `trainable_variables` | List of all trainable layer state. This is equivalent to `layer.trainable_weights`. |
| `trainable_weights` | List of all trainable weight variables of the layer. <br /> These are the weights that get updated by the optimizer during training. |
| `variable_dtype` | The dtype of the state (weights) of the layer. |
| `variables` | List of all layer state, including random seeds. <br /> This extends `layer.weights` to include all state used by the layer including `SeedGenerator`s. Note that metrics variables are not included here, use `metrics_variables` to visit all the metric variables. |
| `weights` | List of all weight variables of the layer. <br /> Unlike, `layer.variables` this excludes metric state and random seeds. |

<br />

## Methods

### `add_loss`

    add_loss(
        loss
    )

Can be called inside of the `call()` method to add a scalar loss.

#### Example:

    class MyLayer(Layer):
        ...
        def call(self, x):
            self.add_loss(ops.sum(x))
            return x

### `add_metric`

    add_metric(
        *args, **kwargs
    )

### `add_variable`

    add_variable(
        shape,
        initializer,
        dtype=None,
        trainable=True,
        autocast=True,
        regularizer=None,
        constraint=None,
        name=None
    )

Add a weight variable to the layer.

Alias of `add_weight()`.

### `add_weight`

    add_weight(
        *args,
        shape=None,
        initializer=None,
        dtype=None,
        trainable=True,
        autocast=True,
        regularizer=None,
        constraint=None,
        aggregation='none',
        overwrite_with_gradient=False,
        name=None
    )

Add a weight variable to the layer.

<br />

<br />

<br />

| Args ||
|---|---|
| `shape` | Shape tuple for the variable. Must be fully-defined (no `None` entries). Defaults to `()` (scalar) if unspecified. |
| `initializer` | Initializer object to use to populate the initial variable value, or string name of a built-in initializer (e.g. `"random_normal"`). If unspecified, defaults to `"glorot_uniform"` for floating-point variables and to `"zeros"` for all other types (e.g. int, bool). |
| `dtype` | Dtype of the variable to create, e.g. `"float32"`. If unspecified, defaults to the layer's variable dtype (which itself defaults to `"float32"` if unspecified). |
| `trainable` | Boolean, whether the variable should be trainable via backprop or whether its updates are managed manually. Defaults to `True`. |
| `autocast` | Boolean, whether to autocast layers variables when accessing them. Defaults to `True`. |
| `regularizer` | Regularizer object to call to apply penalty on the weight. These penalties are summed into the loss function during optimization. Defaults to `None`. |
| `constraint` | Contrainst object to call on the variable after any optimizer update, or string name of a built-in constraint. Defaults to `None`. |
| `aggregation` | Optional string, one of `None`, `"none"`, `"mean"`, `"sum"` or `"only_first_replica"`. Annotates the variable with the type of multi-replica aggregation to be used for this variable when writing custom data parallel training loops. Defaults to `"none"`. |
| `overwrite_with_gradient` | Boolean, whether to overwrite the variable with the computed gradient. This is useful for float8 training. Defaults to `False`. |
| `name` | String name of the variable. Useful for debugging purposes. |

<br />

### `build`

[View source](https://github.com/tensorflow/quantum/blob/v0.7.6/tensorflow_quantum/python/layers/high_level/pqc.py#L320-L322)

    build(
        input_shape
    )

Keras build function.

### `build_from_config`

    build_from_config(
        config
    )

Builds the layer's states with the supplied config dict.

By default, this method calls the `build(config["input_shape"])` method,
which creates weights based on the layer's input shape in the supplied
config. If your config contains other information needed to load the
layer's state, you should override this method.

<br />

<br />

<br />

| Args ||
|---|---|
| `config` | Dict containing the input shape associated with this layer. |

<br />

### `call`

[View source](https://github.com/tensorflow/quantum/blob/v0.7.6/tensorflow_quantum/python/layers/high_level/pqc.py#L324-L356)

    call(
        inputs
    )

Keras call function.

<br />

<br />

<br />

| Args ||
|---|---|
| `inputs` | [`tf.Tensor`](https://www.tensorflow.org/api_docs/python/tf/Tensor) <br /> Tensor of shape \[batch_size\], each entry a serialized circuit (from tfq.convert_to_tensor). |

<br />

<br />

<br />

<br />

| Returns ||
|---|---|
| [`tf.Tensor`](https://www.tensorflow.org/api_docs/python/tf/Tensor) | Tensor of shape \[batch_size, n_operators\], expectation values for each operator. |

<br />

### `compute_mask`

    compute_mask(
        inputs, previous_mask
    )

### `compute_output_shape`

    compute_output_shape(
        *args, **kwargs
    )

### `compute_output_spec`

    compute_output_spec(
        *args, **kwargs
    )

### `count_params`

    count_params()

Count the total number of scalars composing the weights.

<br />

<br />

<br />

| Returns ||
|---|---|
| An integer count. ||

<br />

### `from_config`

    @classmethod
    from_config(
        config
    )

Creates an operation from its config.

This method is the reverse of `get_config`, capable of instantiating the
same operation from the config dictionary.

> [!NOTE]
> **Note:** If you override this method, you might receive a serialized dtype config, which is a `dict`. You can deserialize it as follows:

    if "dtype" in config and isinstance(config["dtype"], dict):
        policy = dtype_policies.deserialize(config["dtype"])

<br />

<br />

<br />

| Args ||
|---|---|
| `config` | A Python dictionary, typically the output of `get_config`. |

<br />

<br />

<br />

<br />

| Returns ||
|---|---|
| An operation instance. ||

<br />

### `get_build_config`

    get_build_config()

Returns a dictionary with the layer's input shape.

This method returns a config dict that can be used by
`build_from_config(config)` to create all states (e.g. Variables and
Lookup tables) needed by the layer.

By default, the config only contains the input shape that the layer
was built with. If you're writing a custom layer that creates state in
an unusual way, you should override this method to make sure this state
is already created when Keras attempts to load its value upon model
loading.

<br />

<br />

<br />

| Returns ||
|---|---|
| A dict containing the input shape associated with the layer. ||

<br />

### `get_config`

    get_config()

Returns the config of the object.

An object config is a Python dictionary (serializable)
containing the information needed to re-instantiate it.

### `get_weights`

    get_weights()

Return the values of `layer.weights` as a list of NumPy arrays.

### `load_own_variables`

    load_own_variables(
        store
    )

Loads the state of the layer.

You can override this method to take full control of how the state of
the layer is loaded upon calling [`keras.models.load_model()`](https://www.tensorflow.org/api_docs/python/tf/keras/models/load_model).

<br />

<br />

<br />

| Args ||
|---|---|
| `store` | Dict from which the state of the model will be loaded. |

<br />

### `quantize`

    quantize(
        mode=None, type_check=True, config=None
    )

### `quantized_build`

    quantized_build(
        input_shape, mode
    )

### `quantized_call`

    quantized_call(
        *args, **kwargs
    )

### `rematerialized_call`

    rematerialized_call(
        layer_call, *args, **kwargs
    )

Enable rematerialization dynamically for layer's call method.

<br />

<br />

<br />

| Args ||
|---|---|
| `layer_call` | The original `call` method of a layer. |

<br />

<br />

<br />

<br />

| Returns ||
|---|---|
| Rematerialized layer's `call` method. ||

<br />

### `save_own_variables`

    save_own_variables(
        store
    )

Saves the state of the layer.

You can override this method to take full control of how the state of
the layer is saved upon calling `model.save()`.

<br />

<br />

<br />

| Args ||
|---|---|
| `store` | Dict where the state of the model will be saved. |

<br />

### `set_weights`

    set_weights(
        weights
    )

Sets the values of `layer.weights` from a list of NumPy arrays.

### `stateless_call`

    stateless_call(
        trainable_variables,
        non_trainable_variables,
        *args,
        return_losses=False,
        **kwargs
    )

Call the layer without any side effects.

<br />

<br />

<br />

| Args ||
|---|---|
| `trainable_variables` | List of trainable variables of the model. |
| `non_trainable_variables` | List of non-trainable variables of the model. |
| `*args` | Positional arguments to be passed to `call()`. |
| `return_losses` | If `True`, `stateless_call()` will return the list of losses created during `call()` as part of its return values. |
| `**kwargs` | Keyword arguments to be passed to `call()`. |

<br />

<br />

<br />

<br />

| Returns ||
|---|---|
| A tuple. By default, returns `(outputs, non_trainable_variables)`. If `return_losses = True`, then returns `(outputs, non_trainable_variables, losses)`. ||

<br />

> [!NOTE]
> **Note:** `non_trainable_variables` include not only non-trainable weights such as `BatchNormalization` statistics, but also RNG seed state (if there are any random operations part of the layer, such as dropout), and `Metric` state (if there are any metrics attached to the layer). These are all elements of state of the layer.

#### Example:

    model = ...
    data = ...
    trainable_variables = model.trainable_variables
    non_trainable_variables = model.non_trainable_variables
    # Call the model with zero side effects
    outputs, non_trainable_variables = model.stateless_call(
        trainable_variables,
        non_trainable_variables,
        data,
    )
    # Attach the updated state to the model
    # (until you do this, the model is still in its pre-call state).
    for ref_var, value in zip(
        model.non_trainable_variables, non_trainable_variables
    ):
        ref_var.assign(value)

### `symbol_values`

[View source](https://github.com/tensorflow/quantum/blob/v0.7.6/tensorflow_quantum/python/layers/high_level/pqc.py#L311-L318)

    symbol_values()

Returns a Python `dict` containing symbol name, value pairs.

<br />

<br />

<br />

| Returns ||
|---|---|
| Python `dict` with `str` keys and `float` values representing the current symbol values. ||

<br />

### `symbolic_call`

    symbolic_call(
        *args, **kwargs
    )

### `__call__`

    __call__(
        *args, **kwargs
    )

Call self as a function.