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.9979+0.0000j, 0.0000-0.0653j]])

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.3695+0.2647j, 0.0000+0.0000j, 0.5187+0.7241j, 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_8e7a4c8433d04b03b05239074a199490 ef9d6d50555b40ecac7d58e0cea3ed5b 0 b8a45487db71426085f1f9313732255d RX(Φ/θ) ef9d6d50555b40ecac7d58e0cea3ed5b--b8a45487db71426085f1f9313732255d ff06869e573b43b9a81196883112fbc2 1 e06a8f2513e340e496d843b6ee351821 b8a45487db71426085f1f9313732255d--e06a8f2513e340e496d843b6ee351821 387d6584715446dc99b95b3c1acd0e8b e06a8f2513e340e496d843b6ee351821--387d6584715446dc99b95b3c1acd0e8b 867db832f8b2408090cc21fc4c08308e HamEvo 387d6584715446dc99b95b3c1acd0e8b--867db832f8b2408090cc21fc4c08308e b17c147894334badbc49b1ba9e175a93 867db832f8b2408090cc21fc4c08308e--b17c147894334badbc49b1ba9e175a93 217cdeb7c5ec4a9c8bb3c320e2029e33 6413363f4f424fad89e97b0b84d77956 RY(2*θ) ff06869e573b43b9a81196883112fbc2--6413363f4f424fad89e97b0b84d77956 36e4d54854df48e080d680c0b076cb6a 2 4bcd60f61d2d486ab2fe0cbf40ee6908 X 6413363f4f424fad89e97b0b84d77956--4bcd60f61d2d486ab2fe0cbf40ee6908 4bcd60f61d2d486ab2fe0cbf40ee6908--e06a8f2513e340e496d843b6ee351821 a114750ba26b41bba260bb3ed91fcac1 4bcd60f61d2d486ab2fe0cbf40ee6908--a114750ba26b41bba260bb3ed91fcac1 b029360156004950978e327ff10320c8 t = Φ a114750ba26b41bba260bb3ed91fcac1--b029360156004950978e327ff10320c8 b029360156004950978e327ff10320c8--217cdeb7c5ec4a9c8bb3c320e2029e33 5f48774e3a894a83a2944072011f2679 c706a6552b0a4ec1bede2640520d63eb RZ(cos(Φ)) 36e4d54854df48e080d680c0b076cb6a--c706a6552b0a4ec1bede2640520d63eb ec0357a3528f46779034cc7ab350fb66 c706a6552b0a4ec1bede2640520d63eb--ec0357a3528f46779034cc7ab350fb66 cf161461aba44d3dbc2c6a43967cad78 PHASE(3.142) ec0357a3528f46779034cc7ab350fb66--cf161461aba44d3dbc2c6a43967cad78 cf161461aba44d3dbc2c6a43967cad78--a114750ba26b41bba260bb3ed91fcac1 825c8122c6c84810a2dd56894e331436 cf161461aba44d3dbc2c6a43967cad78--825c8122c6c84810a2dd56894e331436 825c8122c6c84810a2dd56894e331436--5f48774e3a894a83a2944072011f2679

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.