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.8808+0.0000j, 0.0000-0.4736j]])

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.2410+0.4566j,  0.0000+0.0000j,  0.7574-0.3998j,  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_96869dee9d8e45c393a6306ffdbb0e36 7c10c237979f46988f9732d49f641c14 0 6ae306bbe875495492fff90990310152 RX(Φ/θ) 7c10c237979f46988f9732d49f641c14--6ae306bbe875495492fff90990310152 0bf020c7b65f4e1c9f13ab564b9245de 1 bd1cb807cdcd48758a99dcf3b65367a7 6ae306bbe875495492fff90990310152--bd1cb807cdcd48758a99dcf3b65367a7 d212b1f575e3425c97e5ec38ea9092ff bd1cb807cdcd48758a99dcf3b65367a7--d212b1f575e3425c97e5ec38ea9092ff 9fb9b55e89fb401087f8f3d07d3a0ebd HamEvo d212b1f575e3425c97e5ec38ea9092ff--9fb9b55e89fb401087f8f3d07d3a0ebd c2fb6b9c803242e0ba6297bace4b9335 9fb9b55e89fb401087f8f3d07d3a0ebd--c2fb6b9c803242e0ba6297bace4b9335 d072f2f46a5e484f965c636c51f9b966 f690612ed21f4c99bcf984f3f6676007 RY(2*θ) 0bf020c7b65f4e1c9f13ab564b9245de--f690612ed21f4c99bcf984f3f6676007 6a02ef2262b043bcb172eb8b8b5d468a 2 fafe0e7105584763acfbb8071e7f8319 X f690612ed21f4c99bcf984f3f6676007--fafe0e7105584763acfbb8071e7f8319 fafe0e7105584763acfbb8071e7f8319--bd1cb807cdcd48758a99dcf3b65367a7 aae693b819ca4c248b4ccc80699dd3e6 fafe0e7105584763acfbb8071e7f8319--aae693b819ca4c248b4ccc80699dd3e6 01c2d82845d847c9a712494f9527c288 t = Φ aae693b819ca4c248b4ccc80699dd3e6--01c2d82845d847c9a712494f9527c288 01c2d82845d847c9a712494f9527c288--d072f2f46a5e484f965c636c51f9b966 98a5756cb1644d359aa9de5b690fee90 1a98dec744714cf9a48d0c1820a1e3e9 RZ(cos(Φ)) 6a02ef2262b043bcb172eb8b8b5d468a--1a98dec744714cf9a48d0c1820a1e3e9 e0b2e65375594e8c81b6cdbeb122680b 1a98dec744714cf9a48d0c1820a1e3e9--e0b2e65375594e8c81b6cdbeb122680b 8526d251c4c74194b8d692eae3798b69 PHASE(3.142) e0b2e65375594e8c81b6cdbeb122680b--8526d251c4c74194b8d692eae3798b69 8526d251c4c74194b8d692eae3798b69--aae693b819ca4c248b4ccc80699dd3e6 63deebc114ff4f5c9661167eed2dca22 8526d251c4c74194b8d692eae3798b69--63deebc114ff4f5c9661167eed2dca22 63deebc114ff4f5c9661167eed2dca22--98a5756cb1644d359aa9de5b690fee90

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.