Quantum Encoding Circuits
Quantum encoding circuits are used to embed classical data \(x\) into a quantum state and manipulate the quantum state via trainable parameters \(p\). They are a key component of many quantum machine learning algorithms, and the design of a good quantum encoding circuit is crucial for the performance of the algorithm. In sQUlearn, encoding circuits are an obligatory input in the Quantum Neural Network (QNN) or Quantum Kernel programs. sQUlearn offers a wide range of pre-implemented quantum encoding circuits, which can be combined to create more sophisticated encoding circuits. Furthermore, it is possible to create custom encoding circuits that follow a layered approach, in which each gate is applied to all qubits. The package facilitate a fully automated pruning algorithm to remove redundant parameters and enables the automatic differentiation of arbitrary derivative.
The following functions and classes are are accessible via squlearn.encoding_circuit
.
Implemented Quantum Encoding Circuits
There are several Quantum Encoding Circuits implemented in sQUlearn:
Creates the YZ-CX Encoding Circuit from reference [1]. |
|
The high-dimensional encoding circuit from reference [1]. |
|
Creates the data reuploading encoding circuit as presented in reference [1]. |
|
A feature-map that is based on the Chebyshev Tower encoding. |
|
Chebyshev Encoding Circuit from reference [1]. |
|
Encoding circuit with HZ encoding followed by controlled Rx, Ry Rz rotations. |
|
Simple Chebyshev encoding circuit build from Rx gates |
|
Parameterized Z feature map with optional CNOT gates between the default layers. |
|
Wrapper to create sQUlearn encoding circuits from the Qiskit circuit library. |
Feel free to contribute to sQUlearn by adding your own encoding circuits in a Pull Request.
Example: Create a Hubregtsen encoding circuit
from squlearn.encoding_circuit import HubregtsenEncodingCircuit
pqc = HubregtsenEncodingCircuit(num_qubits=4, num_features=2, num_layers=2)
pqc.draw(output="mpl")
Combining Quantum Encoding Circuits
In sQUlearn, quantum encoding circuits can be combined to create more sophisticated encoding circuits by
utilizing the +
operation between two encoding circuits. However, it is important to note that
the number of qubits in both encoding circuits must match for successful combination.
When combining encoding circuits, the resulting feature dimension is determined by taking the maximum value from the two feature dimensions. The parameters of the individual encoding circuits are concatenated. Consequently, the total number of parameters in the combined encoding circuit is equal to the sum of the parameters in the two original encoding circuits.
Example: combine two quantum encoding circuits
from squlearn.encoding_circuit import HubregtsenEncodingCircuit, ChebyshevPQC
fm1 = HubregtsenEncodingCircuit(num_qubits=4, num_features=2, num_layers=1, closed=False)
fm2 = ChebyshevPQC(num_qubits=4, num_features=3, num_layers=1)
# Combining both encoding circuits
fm3 = fm1 + fm2
fm3.draw(output="mpl")
Wrapping Qiskit Encoding Circuits
It is also possible to utilize the wrapper QiskitEncodingCircuit
to build Encoding Circuits from the
Qiskit circuit library.
from squlearn.encoding_circuit import QiskitEncodingCircuit
from qiskit.circuit.library import TwoLocal
local = TwoLocal(3, 'ry', 'cx', 'linear', reps=2, insert_barriers=True)
QiskitEncodingCircuit(local).draw(output="mpl")
Create your custom Encoding Circuit via LayeredEncodingCircuit
sQUlearn offers a user-friendly solution for creating custom layered encoding circuits effortlessly.
Layered encoding circuits involve the application of gates to all qubits, ensuring a comprehensive
approach. This method allows for the creation of encoding circuits in a structured manner,
regardless of the number of qubits involved.
Two-qubit gates are applied either in a nearest neighbor fashion or by entangling all qubits.
You can construct the layered encoding circuit using either a Qiskit Quantum circuit-inspired approach
or by providing a string using the
LayeredEncodingCircuit.from_string()
method. For detailed instructions on the string format, please refer to the documentation of
the LayeredEncodingCircuit
class.
Example: Create your custom layered encoding circuit
from squlearn.encoding_circuit import LayeredEncodingCircuit
from squlearn.encoding_circuit.layered_encoding_circuit import Layer
encoding_circuit = LayeredEncodingCircuit(num_qubits=4,num_features=2)
encoding_circuit.H()
layer = Layer(encoding_circuit)
layer.Rz("x")
layer.Ry("p")
layer.cx_entangling("NN")
encoding_circuit.add_layer(layer,num_layers=3)
encoding_circuit.draw(output="mpl")
Example: Create your custom layered encoding circuit from a string
from squlearn.encoding_circuit import LayeredEncodingCircuit
encoding_circuit = LayeredEncodingCircuit.from_string(
"Ry(p)-3[Rx(p,x;=y*np.arccos(x),{y,x})-crz(p)]-Ry(p)", num_qubits=4, num_features=1, num_layers=2
)
encoding_circuit.draw(output="mpl")
Pruning of Quantum Encoding Circuits
It is also possible to remove parameterized gates from a quantum encoding circuit by using the
PrunedEncodingCircuit
class.
This class accepts a quantum encoding circuit as input and removes the parameterized gates
from the encoding circuit for the parameters which indices are specified in the supplied list.
The pruned encoding circuit automatically adjusts the number of parameters and features.
Furthermore it is possible to determine the redundant parameters in encoding circuit automatically. The algorithm is based on https://doi.org/10.1103/PRXQuantum.2.040309 and is based on evaluating the Quantum Fisher Information Matrix (QFIM) of the encoding circuit.
sQUlearn features a fully automated pruning algorithm which can be used by calling the routine
automated_pruning()
that returns a pruned encoding circuit without the redundant parameters.
Example: Pruning a encoding circuit with redundant parameters
from squlearn.encoding_circuit import LayeredEncodingCircuit, automated_pruning
from squlearn.util import Executor
encoding_circuit = LayeredEncodingCircuit.from_string("Rz(p)-Ry(p)-Z-Ry(p)-Rz(p)", num_qubits=2, num_features=0)
pruned_encoding_circuit = automated_pruning(encoding_circuit, Executor())
pruned_encoding_circuit.draw(output="mpl")
Pruned parameters: [0 1 2 3]
Different Quantum Encoding Circuits via EncodingCircuitDerivatives
The calculation of derivatives for quantum encoding circuits is often essential in training a
Quantum Machine Learning model. In sQUlearn, we offer a straightforward approach to compute
these derivatives using the EncodingCircuitDerivatives
class.
This class accepts an existing quantum encoding circuit as input and generates derivatives of the
encoding circuit with respect to its parameters or features. The derivative circuits are generated
by leveraging the parameter-shift rule and are cached for future use.
Use the function get_derivative()
to obtain the derivative. There are several options to specify the derivative you want to obtain:
Provide a string that specifies the derivative you want to obtain. A list of the available strings can be found in the documentation of the
EncodingCircuitDerivatives
class.Provide a tuple containing the ParameterVector or an element of the ParameterVector to obtain higher order derivatives. The derivatives are applied successively following the order in the tuple.
Provide a list of ParameterVector elements to obtain the derivatives of the specified elements. This can also be placed in the tuple.
The derivatives are stored in sQUlearn’s proprietary OpTree structure, which is utilized for the arithmetic operations of the derivatives.
Example: Obtain the derivative of a Hubregtsen encoding circuit
from squlearn.encoding_circuit import HubregtsenEncodingCircuit, EncodingCircuitDerivatives
fm = HubregtsenEncodingCircuit(num_qubits=2, num_features=2, num_layers=2)
fm_deriv = EncodingCircuitDerivatives(fm)
# From String (gradient of the parameter vector)
grad_from_string = fm_deriv.get_derivative("dp")
# From Tuple (second order derivative of the parameter vector; equal to the Hessian)
grad_from_tuple = fm_deriv.get_derivative((fm_deriv.parameter_vector,fm_deriv.parameter_vector))
# From List (only partial derivatives of the first two parameters)
grad_from_List = fm_deriv.get_derivative(([fm_deriv.parameter_vector[0],
fm_deriv.parameter_vector[1]],
))
Transpile Quantum Encoding Circuits via TranspiledEncodingCircuit
To transpile a quantum encoding circuit, you can leverage the functionality provided by the
TranspiledEncodingCircuit
class. By utilizing this class, you can input an existing
quantum encoding circuit and have its circuit transpiled according to the specified backend and
transpiler settings, which are the same settings used in Qiskit.
The transpiled encoding circuit is internally employed in the QNN program and projected kernels,
where it is employed internally.
Example: Transpile a existing Encoding Circuit to a fake backend
from squlearn.encoding_circuit import TranspiledEncodingCircuit,ChebyshevRx
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
fm = TranspiledEncodingCircuit(ChebyshevRx(3,1),backend=FakeManilaV2(),initial_layout=[0,1,4])
fm.draw(output="mpl")