Skip to content

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

Passing fixed parameters to blocks can be done by simply passing a Python numeric type or a torch.Tensor.

import torch
from 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

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

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 tensor
from 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

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 tensor
from qadence import RX, Z, HamEvo, PI
from qadence import VariationalParameter, FeatureParameter, run
from sympy import sin

theta, phi = VariationalParameter("theta"), FeatureParameter("phi")

# Arbitrary parameter composition
expr = PI * sin(theta + phi)

# Use as unitary gate arguments
gate = RX(0, expr)

# Or as scaling coefficients for Hermitian operators
h_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

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 tensor
from 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

Let's look at a final example of an arbitrary composition of digital and analog parameterized blocks:

import sympy
from qadence import RX, RY, RZ, CNOT, CPHASE, Z, HamEvo
from 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)
%3 cluster_809c9b2a26f54d068ca440ece0dc4fcf 8bce00e5a1694ebc8bf08601d63d6018 0 2f05bb5ff7684440a474d24024331af3 RX(Φ/θ) 8bce00e5a1694ebc8bf08601d63d6018--2f05bb5ff7684440a474d24024331af3 6623b773b34949fbba2cb9c7de932b93 1 627d1375cba74d5eb8f916dd2919431a 2f05bb5ff7684440a474d24024331af3--627d1375cba74d5eb8f916dd2919431a 5bc93949688b4f60940c6c0bdae3feee 627d1375cba74d5eb8f916dd2919431a--5bc93949688b4f60940c6c0bdae3feee db3595b4d2074cd39ef01b47674b47ad HamEvo 5bc93949688b4f60940c6c0bdae3feee--db3595b4d2074cd39ef01b47674b47ad 18bd2a6ad0924204afe3055b8c5ea9db db3595b4d2074cd39ef01b47674b47ad--18bd2a6ad0924204afe3055b8c5ea9db ee6bd6b61b084f1f871d7bbbc5369b61 2db4aebbd32743f4ac4bdc3acc7e8782 RY(2*θ) 6623b773b34949fbba2cb9c7de932b93--2db4aebbd32743f4ac4bdc3acc7e8782 23bc3ffbc4a74e63ad1d6ef1e3ab9ca1 2 4db28ffb07744e739498331362646370 X 2db4aebbd32743f4ac4bdc3acc7e8782--4db28ffb07744e739498331362646370 4db28ffb07744e739498331362646370--627d1375cba74d5eb8f916dd2919431a e0179c859d294fa9bb176cc4fa5407f5 4db28ffb07744e739498331362646370--e0179c859d294fa9bb176cc4fa5407f5 7f9b3c09389a40a79d58260710f05f94 t = Φ e0179c859d294fa9bb176cc4fa5407f5--7f9b3c09389a40a79d58260710f05f94 7f9b3c09389a40a79d58260710f05f94--ee6bd6b61b084f1f871d7bbbc5369b61 6fba849cb7134803a0600ab4bad05779 10995fb246464729a04e25059a906573 RZ(cos(Φ)) 23bc3ffbc4a74e63ad1d6ef1e3ab9ca1--10995fb246464729a04e25059a906573 069e1c9ac3574f34ab57f9ecae09379b 10995fb246464729a04e25059a906573--069e1c9ac3574f34ab57f9ecae09379b 44a4a4f713de432595e2b511f28fe16d PHASE(3.142) 069e1c9ac3574f34ab57f9ecae09379b--44a4a4f713de432595e2b511f28fe16d 44a4a4f713de432595e2b511f28fe16d--e0179c859d294fa9bb176cc4fa5407f5 54b03e6abc6e459c8228c3e2adb17dc8 44a4a4f713de432595e2b511f28fe16d--54b03e6abc6e459c8228c3e2adb17dc8 54b03e6abc6e459c8228c3e2adb17dc8--6fba849cb7134803a0600ab4bad05779

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.