From 77194ecd2bfcbdc3374e67f8818ee35c5faff99e Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Thu, 4 Sep 2025 14:19:01 +0530 Subject: [PATCH 1/5] Improve docstrings for PQC and Expectation layers for clarity and TensorFlow style --- .../layers/circuit_executors/expectation.py | 38 ++++++++++++++----- .../python/layers/high_level/pqc.py | 28 +++++++++++++- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/tensorflow_quantum/python/layers/circuit_executors/expectation.py b/tensorflow_quantum/python/layers/circuit_executors/expectation.py index c3b1d913e..36ed2ca0c 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/expectation.py +++ b/tensorflow_quantum/python/layers/circuit_executors/expectation.py @@ -30,6 +30,23 @@ class Expectation(tf.keras.layers.Layer): """A Layer that calculates an expectation value. + Args: + backend (Union[str, cirq.Sampler, cirq.sim.simulator.SimulatesExpectationValues], optional): + Backend simulator to use. Default is 'noiseless'. + differentiator (Optional[tfq.differentiators.Differentiator]): + Differentiation scheme for gradients. + **kwargs: Additional keyword arguments for the parent class. + + Input shape: + - circuits: tf.Tensor or list of shape [batch_size], each entry a serialized circuit (from tfq.convert_to_tensor). + - symbol_names: list or tf.Tensor of shape [n_symbols], names of circuit parameters (optional). + - symbol_values: tf.Tensor of shape [batch_size, n_symbols], values for circuit parameters (optional). + - operators: list or tf.Tensor of shape [n_ops], observables to measure (optional). + - repetitions: int or tf.Tensor, number of measurement repetitions (optional, only for noisy backend). + + Output shape: + tf.Tensor of shape [batch_size, n_ops], expectation values for each circuit and operator. + Given an input circuit and set of parameter values, prepare a quantum state and output expectation values taken on that state with respect to some observables to the tensorflow graph. @@ -273,15 +290,18 @@ def call(self, initializer=tf.keras.initializers.RandomUniform(0, 2 * np.pi)): """Keras call function. - Input options: - `inputs`, `symbol_names`, `symbol_values`: - see `input_checks.expand_circuits` - `operators`: see `input_checks.expand_operators` - - Output shape: - `tf.Tensor` with shape [batch_size, n_ops] that holds the - expectation value for each circuit with each op applied to it - (after resolving the corresponding parameters in). + Args: + inputs (tf.Tensor or list): Circuits to execute, shape [batch_size]. + symbol_names (list or tf.Tensor, optional): Names of circuit parameters, shape [n_symbols]. + symbol_values (tf.Tensor, optional): Values for circuit parameters, shape [batch_size, n_symbols]. + operators (list or tf.Tensor, optional): Observables to measure, shape [n_ops]. + repetitions (int or tf.Tensor, optional): Number of measurement repetitions (for noisy backend). + initializer (tf.keras.initializers.Initializer, optional): Initializer for circuit parameters. + + Returns: + tf.Tensor: Tensor of shape [batch_size, n_ops] that holds the + expectation value for each circuit with each op applied to it + (after resolving the corresponding parameters in). """ values_empty = False if symbol_values is None: diff --git a/tensorflow_quantum/python/layers/high_level/pqc.py b/tensorflow_quantum/python/layers/high_level/pqc.py index 0f38c35a7..e89f3693b 100644 --- a/tensorflow_quantum/python/layers/high_level/pqc.py +++ b/tensorflow_quantum/python/layers/high_level/pqc.py @@ -28,6 +28,23 @@ class PQC(tf.keras.layers.Layer): """Parametrized Quantum Circuit (PQC) Layer. + Args: + model_circuit (cirq.Circuit): Circuit with sympy.Symbols to be trained. + operators (Union[cirq.PauliSum, cirq.PauliString, list]): Observable(s) to measure. + repetitions (Optional[int]): 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]): Differentiation scheme. + initializer (tf.keras.initializers.Initializer): Initializer for circuit parameters. + regularizer (Optional[tf.keras.regularizers.Regularizer]): Regularizer for circuit parameters. + constraint (Optional[tf.keras.constraints.Constraint]): Constraint for circuit parameters. + **kwargs: Additional keyword arguments for the parent class. + + Input shape: + tf.Tensor of shape [batch_size], each entry a serialized circuit (from tfq.convert_to_tensor). + + Output shape: + tf.Tensor of shape [batch_size, n_operators], expectation values for each operator. + 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. @@ -293,7 +310,16 @@ def build(self, input_shape): super().build(input_shape) def call(self, inputs): - """Keras call function.""" + """Keras call function. + + Args: + inputs (tf.Tensor): Tensor of shape [batch_size], each entry a + serialized circuit (from tfq.convert_to_tensor). + + Returns: + tf.Tensor: Tensor of shape [batch_size, n_operators], + expectation values for each operator. + """ circuit_batch_dim = tf.gather(tf.shape(inputs), 0) tiled_up_model = tf.tile(self._model_circuit, [circuit_batch_dim]) model_appended = self._append_layer(inputs, append=tiled_up_model) From 0176a67e2b4e628ac0fac4aca51cf4a436aaf99f Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Sat, 13 Sep 2025 19:52:19 +0530 Subject: [PATCH 2/5] Fixed format error in docs --- .../python/layers/high_level/pqc.py | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tensorflow_quantum/python/layers/high_level/pqc.py b/tensorflow_quantum/python/layers/high_level/pqc.py index e89f3693b..c8a987ed2 100644 --- a/tensorflow_quantum/python/layers/high_level/pqc.py +++ b/tensorflow_quantum/python/layers/high_level/pqc.py @@ -29,21 +29,32 @@ class PQC(tf.keras.layers.Layer): """Parametrized Quantum Circuit (PQC) Layer. Args: - model_circuit (cirq.Circuit): Circuit with sympy.Symbols to be trained. - operators (Union[cirq.PauliSum, cirq.PauliString, list]): Observable(s) to measure. - repetitions (Optional[int]): 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]): Differentiation scheme. - initializer (tf.keras.initializers.Initializer): Initializer for circuit parameters. - regularizer (Optional[tf.keras.regularizers.Regularizer]): Regularizer for circuit parameters. - constraint (Optional[tf.keras.constraints.Constraint]): Constraint for circuit parameters. + model_circuit (cirq.Circuit): + Circuit with sympy.Symbols to be trained. + operators (Union[cirq.PauliSum, cirq.PauliString, list]): + Observable(s) to measure. + repetitions (Optional[int]): + 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]): + Differentiation scheme. + initializer (tf.keras.initializers.Initializer): + Initializer for circuit parameters. + regularizer (Optional[tf.keras.regularizers.Regularizer]): + Regularizer for circuit parameters. + constraint (Optional[tf.keras.constraints.Constraint]): + Constraint for circuit parameters. **kwargs: Additional keyword arguments for the parent class. Input shape: - tf.Tensor of shape [batch_size], each entry a serialized circuit (from tfq.convert_to_tensor). + tf.Tensor of shape [batch_size], each entry a serialized circuit + (from tfq.convert_to_tensor). Output shape: - tf.Tensor of shape [batch_size, n_operators], expectation values for each operator. + tf.Tensor of shape [batch_size, n_operators], expectation values + for each operator. This layer is for training parameterized quantum models. Given a parameterized circuit, this layer initializes the parameters From c588e1fc75bda21b10a532a97ff2af510e7bfc75 Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Sat, 13 Sep 2025 19:57:32 +0530 Subject: [PATCH 3/5] Fixed format error in docs --- tensorflow_quantum/python/layers/high_level/pqc.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tensorflow_quantum/python/layers/high_level/pqc.py b/tensorflow_quantum/python/layers/high_level/pqc.py index c8a987ed2..81fe97410 100644 --- a/tensorflow_quantum/python/layers/high_level/pqc.py +++ b/tensorflow_quantum/python/layers/high_level/pqc.py @@ -34,7 +34,8 @@ class PQC(tf.keras.layers.Layer): operators (Union[cirq.PauliSum, cirq.PauliString, list]): Observable(s) to measure. repetitions (Optional[int]): - Number of measurement repetitions. If None, analytic expectation is used. + Number of measurement repetitions. If None, analytic + expectation is used. backend (Union[str, cirq.Sampler, cirq.sim.simulator.SimulatesExpectationValues]): Backend simulator. From d54c3f404eca4a99c6be9b728a69cf25dfbafd68 Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Sat, 13 Sep 2025 22:25:18 +0530 Subject: [PATCH 4/5] Fixed format error in docs --- .../layers/circuit_executors/expectation.py | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/tensorflow_quantum/python/layers/circuit_executors/expectation.py b/tensorflow_quantum/python/layers/circuit_executors/expectation.py index 36ed2ca0c..3daab6e29 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/expectation.py +++ b/tensorflow_quantum/python/layers/circuit_executors/expectation.py @@ -31,21 +31,28 @@ class Expectation(tf.keras.layers.Layer): """A Layer that calculates an expectation value. Args: - backend (Union[str, cirq.Sampler, cirq.sim.simulator.SimulatesExpectationValues], optional): + backend (Union[str, cirq.Sampler, + cirq.sim.simulator.SimulatesExpectationValues], optional): Backend simulator to use. Default is 'noiseless'. differentiator (Optional[tfq.differentiators.Differentiator]): Differentiation scheme for gradients. **kwargs: Additional keyword arguments for the parent class. Input shape: - - circuits: tf.Tensor or list of shape [batch_size], each entry a serialized circuit (from tfq.convert_to_tensor). - - symbol_names: list or tf.Tensor of shape [n_symbols], names of circuit parameters (optional). - - symbol_values: tf.Tensor of shape [batch_size, n_symbols], values for circuit parameters (optional). - - operators: list or tf.Tensor of shape [n_ops], observables to measure (optional). - - repetitions: int or tf.Tensor, number of measurement repetitions (optional, only for noisy backend). + - circuits: tf.Tensor or list of shape [batch_size], each entry a + serialized circuit (from tfq.convert_to_tensor). + - symbol_names: list or tf.Tensor of shape [n_symbols], names of + circuit parameters (optional). + - symbol_values: tf.Tensor of shape [batch_size, n_symbols], values for + circuit parameters (optional). + - operators: list or tf.Tensor of shape [n_ops], observables to measure + (optional). + - repetitions: int or tf.Tensor, number of measurement repetitions + (optional, only for noisy backend). Output shape: - tf.Tensor of shape [batch_size, n_ops], expectation values for each circuit and operator. + tf.Tensor of shape [batch_size, n_ops], expectation values for each + circuit and operator. Given an input circuit and set of parameter values, prepare a quantum state and output expectation values taken on that state with respect to some @@ -292,11 +299,16 @@ def call(self, Args: inputs (tf.Tensor or list): Circuits to execute, shape [batch_size]. - symbol_names (list or tf.Tensor, optional): Names of circuit parameters, shape [n_symbols]. - symbol_values (tf.Tensor, optional): Values for circuit parameters, shape [batch_size, n_symbols]. - operators (list or tf.Tensor, optional): Observables to measure, shape [n_ops]. - repetitions (int or tf.Tensor, optional): Number of measurement repetitions (for noisy backend). - initializer (tf.keras.initializers.Initializer, optional): Initializer for circuit parameters. + symbol_names (list or tf.Tensor, optional): Names of circuit + parameters, shape [n_symbols]. + symbol_values (tf.Tensor, optional): Values for circuit parameters, + shape [batch_size, n_symbols]. + operators (list or tf.Tensor, optional): Observables to measure, + shape [n_ops]. + repetitions (int or tf.Tensor, optional): Number of measurement + repetitions (for noisy backend). + initializer (tf.keras.initializers.Initializer, optional): + Initializer for circuit parameters. Returns: tf.Tensor: Tensor of shape [batch_size, n_ops] that holds the From a227efedcdc1c70263acf10f064a7d638f575be4 Mon Sep 17 00:00:00 2001 From: Aniket Singh Yadav Date: Sun, 14 Sep 2025 23:50:05 +0530 Subject: [PATCH 5/5] Improve Expectation layer docstrings and fix minor issues --- .../python/layers/circuit_executors/expectation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow_quantum/python/layers/circuit_executors/expectation.py b/tensorflow_quantum/python/layers/circuit_executors/expectation.py index 3daab6e29..37c3fe644 100644 --- a/tensorflow_quantum/python/layers/circuit_executors/expectation.py +++ b/tensorflow_quantum/python/layers/circuit_executors/expectation.py @@ -223,10 +223,9 @@ class Expectation(tf.keras.layers.Layer): something like `tfq.layers.Expectation()(cirq.Circuit(...), ...)` please be sure to instead use `tfq.layers.Expectation()(circuit_input, ...)` where `circuit_input` is a `tf.keras.Input` that is filled with - `tfq.conver_to_tensor([cirq.Circuit(..)] * batch_size)` at runtime. This + `tfq.convert_to_tensor([cirq.Circuit(..)] * batch_size)` at runtime. This is because compiled Keras models require non keyword layer `call` inputs to be traceable back to a `tf.keras.Input`. - """ def __init__(self, backend='noiseless', differentiator=None, **kwargs): @@ -249,6 +248,7 @@ def __init__(self, backend='noiseless', differentiator=None, **kwargs): which uses `tfq.differentiators.ParameterShift()`. If `backend` is also 'noiseless' then default is `tfq.differentiators.Adjoint`. + **kwargs: Additional keyword arguments for the parent class. """ super().__init__(**kwargs)