Parametric programs
Qadence provides a flexible parameter system built on top of Sympy. Parameters can be of different types:
- Fixed parameter: a constant with a fixed, non-trainable value (e.g. \(\dfrac{\pi}{2}\)).
- Variational parameter: a trainable parameter which will be automatically picked up by the optimizer.
- Feature parameter: a non-trainable parameter which can be used to pass input values.
Fixed parameters
Section titled “Fixed parameters”Passing fixed parameters to blocks can be done by simply passing a Python numeric type or a torch.Tensor.
import torchfrom qadence import RX, run, PI
wf = run(RX(0, torch.tensor(PI)))
wf = run(RX(0, PI))wf = tensor([[6.1232e-17+0.j, 0.0000e+00-1.j]])wf = tensor([[6.1232e-17+0.j, 0.0000e+00-1.j]])Variational parameters
Section titled “Variational parameters”To parametrize a block a VariationalParameter instance is required. In most cases Qadence also accepts a Python string, which will be used to automatically initialize a VariationalParameter:
from qadence import RX, run, VariationalParameter
block = RX(0, VariationalParameter("theta"))block = RX(0, "theta") # Equivalent
wf = run(block)wf = tensor([[0.9949+0.0000j, 0.0000-0.1006j]])By calling run, a random value for "theta" is initialized at execution. In a QuantumModel, variational parameters are stored in the underlying model parameter dictionary.
Feature parameters
Section titled “Feature parameters”A FeatureParameter type can also be used. It requires an input value or a batch of values. In most cases, Qadence accepts a values dictionary to set the input of feature parameters.
from torch import tensorfrom qadence import RX, PI, run, FeatureParameter
block = RX(0, FeatureParameter("phi"))
wf = run(block, values = {"phi": tensor([PI, PI/2])})wf = tensor([[6.1232e-17+0.0000j, 0.0000e+00-1.0000j], [7.0711e-01+0.0000j, 0.0000e+00-0.7071j]])Since a batch of input values was passed, the run function returns a batch of output states. Note that FeatureParameter("x") and VariationalParameter("x") are simply aliases for Parameter("x", trainable = False) and Parameter("x", trainable = True).
Multiparameter expressions and analog integration
Section titled “Multiparameter expressions and analog integration”The integration with Sympy becomes useful when one wishes to write arbitrary parameter compositions. Parameters can also be used as scaling coefficients in the block system, which is essential when defining arbitrary analog operations.
from torch import tensorfrom qadence import RX, Z, HamEvo, PIfrom qadence import VariationalParameter, FeatureParameter, runfrom sympy import sin
theta, phi = VariationalParameter("theta"), FeatureParameter("phi")
# Arbitrary parameter compositionexpr = PI * sin(theta + phi)
# Use as unitary gate argumentsgate = RX(0, expr)
# Or as scaling coefficients for Hermitian operatorsh_op = expr * (Z(0) @ Z(1))
wf = run(gate * HamEvo(h_op, 1.0), values = {"phi": tensor(PI)})wf = tensor([[-0.2592+0.2091j, 0.0000+0.0000j, 0.5922-0.7338j, 0.0000+0.0000j]])Parameter redundancy
Section titled “Parameter redundancy”Parameters are uniquely defined by their name and redundancy is allowed in composite blocks to assign the same value to different blocks. This is useful, for example, when defining layers of rotation gates typically used as feature maps.
from torch import tensorfrom qadence import RY, PI, run, kron, FeatureParameter
n_qubits = 3
param = FeatureParameter("phi")
block = kron(RY(i, (i+1) * param) for i in range(n_qubits))
wf = run(block, values = {"phi": tensor(PI)})wf = tensor([[ 1.1248e-32+0.j, 6.1232e-17+0.j, -1.3775e-48+0.j, -7.4988e-33+0.j, 1.8370e-16+0.j, 1.0000e+00+0.j, -2.2496e-32+0.j, -1.2246e-16+0.j]])Parametrized circuits
Section titled “Parametrized circuits”Let's look at a final example of an arbitrary composition of digital and analog parameterized blocks:
import sympyfrom qadence import RX, RY, RZ, CNOT, CPHASE, Z, HamEvofrom qadence import run, chain, add, kron, FeatureParameter, VariationalParameter, PI
n_qubits = 3
phi = FeatureParameter("Φ")theta = VariationalParameter("θ")
rotation_block = kron( RX(0, phi/theta), RY(1, theta*2), RZ(2, sympy.cos(phi)))digital_entangler = CNOT(0, 1) * CPHASE(1, 2, PI)
hamiltonian = add(theta * (Z(i) @ Z(i+1)) for i in range(n_qubits-1))
analog_evo = HamEvo(hamiltonian, phi)
program = chain(rotation_block, digital_entangler, analog_evo)Please note the different colors for the parametrization with different types. The default palette assigns blue for VariationalParameter, green for FeatureParameter, orange for numeric values, and shaded red for non-parametric gates.