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.9998+0.0000j, 0.0000-0.0179j]])

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.9388+0.3065j, 0.0000+0.0000j, 0.0488+0.1493j, 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_3c162995d077406cab6854c374e053c5 79c19cb22f1b4dc489dc8adcf04c0f1d 0 a3fd1a6a8c7648889e6815131c729ad8 RX(Φ/θ) 79c19cb22f1b4dc489dc8adcf04c0f1d--a3fd1a6a8c7648889e6815131c729ad8 ea29da16d0744d29a6d0fd8eafef7782 1 80964c0cf5974601a7d52517cbd2e694 a3fd1a6a8c7648889e6815131c729ad8--80964c0cf5974601a7d52517cbd2e694 9ce5466846e1441e843b2dce4c30260e 80964c0cf5974601a7d52517cbd2e694--9ce5466846e1441e843b2dce4c30260e 1d893f92cf54408d98e41c94db404e11 HamEvo 9ce5466846e1441e843b2dce4c30260e--1d893f92cf54408d98e41c94db404e11 cedbf9fc713a4c0f99acd105475577c8 1d893f92cf54408d98e41c94db404e11--cedbf9fc713a4c0f99acd105475577c8 01224581639f42f5a0368d3151df0d2c 637afc3e93714a3eb084ba18a0464ca7 RY(2*θ) ea29da16d0744d29a6d0fd8eafef7782--637afc3e93714a3eb084ba18a0464ca7 6ab99669d6984e5db6330b52bfbeb61a 2 c4bfb5d042de439f80074c94e52a1ad9 X 637afc3e93714a3eb084ba18a0464ca7--c4bfb5d042de439f80074c94e52a1ad9 c4bfb5d042de439f80074c94e52a1ad9--80964c0cf5974601a7d52517cbd2e694 a4d9a4492ee04d309a9ce1cd3fa09def c4bfb5d042de439f80074c94e52a1ad9--a4d9a4492ee04d309a9ce1cd3fa09def 588d90b970954ebb8cf0389bcfe5f632 t = Φ a4d9a4492ee04d309a9ce1cd3fa09def--588d90b970954ebb8cf0389bcfe5f632 588d90b970954ebb8cf0389bcfe5f632--01224581639f42f5a0368d3151df0d2c 5213f088bb58466cbb98d9f69b846de7 bbb0fb1e474f4920aa69a00bd4d197fe RZ(cos(Φ)) 6ab99669d6984e5db6330b52bfbeb61a--bbb0fb1e474f4920aa69a00bd4d197fe 2d855d276d7b4d84ad9239bdb7984231 bbb0fb1e474f4920aa69a00bd4d197fe--2d855d276d7b4d84ad9239bdb7984231 5f9a197fd40d473aaa83689812011cfc PHASE(3.142) 2d855d276d7b4d84ad9239bdb7984231--5f9a197fd40d473aaa83689812011cfc 5f9a197fd40d473aaa83689812011cfc--a4d9a4492ee04d309a9ce1cd3fa09def c2bedff551f9470182463fc3e8f6570f 5f9a197fd40d473aaa83689812011cfc--c2bedff551f9470182463fc3e8f6570f c2bedff551f9470182463fc3e8f6570f--5213f088bb58466cbb98d9f69b846de7

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.