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.9133+0.0000j, 0.0000-0.4072j]])

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, phi), values = {"phi": tensor(PI)})
wf = tensor([[-0.8718+0.1986j,  0.0000+0.0000j,  0.0995-0.4367j,  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_e900e8d7a6ed421e9bfa256b1a3734e5 3d6d1155deed4bf1ab0959dbde6ddd53 0 fc7751ae50df4682aa340521e348d0f9 RX(Φ/θ) 3d6d1155deed4bf1ab0959dbde6ddd53--fc7751ae50df4682aa340521e348d0f9 a9caaf5f12974d85abe2532180a8efde 1 a7b05085bbbf4d4fbf9e337fd3da5632 fc7751ae50df4682aa340521e348d0f9--a7b05085bbbf4d4fbf9e337fd3da5632 3e98d12deba74d62a1d5ee7de0664b39 a7b05085bbbf4d4fbf9e337fd3da5632--3e98d12deba74d62a1d5ee7de0664b39 dc745ad43acd431f84097b6ec05d8d7b HamEvo 3e98d12deba74d62a1d5ee7de0664b39--dc745ad43acd431f84097b6ec05d8d7b 96d581b1c962450b841b1d7e83bbf37c dc745ad43acd431f84097b6ec05d8d7b--96d581b1c962450b841b1d7e83bbf37c 68383d0df63e436e943822edb173120b 8788149c06bb44ba929a06a2b6adc69b RY(2*θ) a9caaf5f12974d85abe2532180a8efde--8788149c06bb44ba929a06a2b6adc69b 260c11feed62483bb4d36dc844dcfb9f 2 c605dea438304a4c9147b0fe37d88018 X 8788149c06bb44ba929a06a2b6adc69b--c605dea438304a4c9147b0fe37d88018 c605dea438304a4c9147b0fe37d88018--a7b05085bbbf4d4fbf9e337fd3da5632 007dc9c304e143858e8e3c7263386302 c605dea438304a4c9147b0fe37d88018--007dc9c304e143858e8e3c7263386302 d875b16467164b36a8b9ef34ca499c06 t = Φ 007dc9c304e143858e8e3c7263386302--d875b16467164b36a8b9ef34ca499c06 d875b16467164b36a8b9ef34ca499c06--68383d0df63e436e943822edb173120b cb52fd6281ed43cfb8d0044d8559ba95 97b0a97ff5414769b3888685bf2a1b8b RZ(cos(Φ)) 260c11feed62483bb4d36dc844dcfb9f--97b0a97ff5414769b3888685bf2a1b8b e4a10ac8c79a47ae9cf28a30c4c36ecd 97b0a97ff5414769b3888685bf2a1b8b--e4a10ac8c79a47ae9cf28a30c4c36ecd 2f63ff5c91e542539f6a24036e355a50 PHASE(3.142) e4a10ac8c79a47ae9cf28a30c4c36ecd--2f63ff5c91e542539f6a24036e355a50 2f63ff5c91e542539f6a24036e355a50--007dc9c304e143858e8e3c7263386302 7d24f22839a140d0b0cd9e7d6bb6b251 2f63ff5c91e542539f6a24036e355a50--7d24f22839a140d0b0cd9e7d6bb6b251 7d24f22839a140d0b0cd9e7d6bb6b251--cb52fd6281ed43cfb8d0044d8559ba95

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.