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.0648j]])

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.2498+0.1812j,  0.0000+0.0000j,  0.5584-0.7700j,  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_782de171f85040e49d93075e59118b64 2e6ff3aeda064f86a94e1de91d5d8233 0 2547012b16c6452493aeac5dc7744efb RX(Φ/θ) 2e6ff3aeda064f86a94e1de91d5d8233--2547012b16c6452493aeac5dc7744efb 4a967131ec69411e8ec64265fc26f695 1 d4d32140d5c7407484ee97dc15319a9b 2547012b16c6452493aeac5dc7744efb--d4d32140d5c7407484ee97dc15319a9b a8508667106b4819a29de35b7a7f5ccd d4d32140d5c7407484ee97dc15319a9b--a8508667106b4819a29de35b7a7f5ccd b7fe1515e76a4b4db82d1cd3f3a1d5db HamEvo a8508667106b4819a29de35b7a7f5ccd--b7fe1515e76a4b4db82d1cd3f3a1d5db 4ef805f98cf8443caa2acf4a19ee3b39 b7fe1515e76a4b4db82d1cd3f3a1d5db--4ef805f98cf8443caa2acf4a19ee3b39 a5385c2886d342bf91d89732fa7c1ac9 5b53fc10f5914e22bd34eb51109bf609 RY(2*θ) 4a967131ec69411e8ec64265fc26f695--5b53fc10f5914e22bd34eb51109bf609 90d3dbd25bb544b78585c517f32dd90e 2 21d18fcd0e4d4da3b0ffaad8d982709f X 5b53fc10f5914e22bd34eb51109bf609--21d18fcd0e4d4da3b0ffaad8d982709f 21d18fcd0e4d4da3b0ffaad8d982709f--d4d32140d5c7407484ee97dc15319a9b 0354b279584c4457acbbd1bdadd13b2d 21d18fcd0e4d4da3b0ffaad8d982709f--0354b279584c4457acbbd1bdadd13b2d 5336f135bf6540c3a7b6ecedc5ff414e t = Φ 0354b279584c4457acbbd1bdadd13b2d--5336f135bf6540c3a7b6ecedc5ff414e 5336f135bf6540c3a7b6ecedc5ff414e--a5385c2886d342bf91d89732fa7c1ac9 578c5f1237e84bbb80db80bdcf51274a 6a1f8580b1964c7b978da6dc0f5fc77c RZ(cos(Φ)) 90d3dbd25bb544b78585c517f32dd90e--6a1f8580b1964c7b978da6dc0f5fc77c 66d43924e0c84d2e906b693b68cece00 6a1f8580b1964c7b978da6dc0f5fc77c--66d43924e0c84d2e906b693b68cece00 83876653505046b8b0614b54dc203a9e PHASE(3.142) 66d43924e0c84d2e906b693b68cece00--83876653505046b8b0614b54dc203a9e 83876653505046b8b0614b54dc203a9e--0354b279584c4457acbbd1bdadd13b2d a157253efba2411da768b24c13a931dc 83876653505046b8b0614b54dc203a9e--a157253efba2411da768b24c13a931dc a157253efba2411da768b24c13a931dc--578c5f1237e84bbb80db80bdcf51274a

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.