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.8786+0.0000j, 0.0000-0.4775j]])

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([[9.9997e-01+0.0065j, 0.0000e+00+0.0000j, 2.0918e-05+0.0032j,
         0.0000e+00+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_962e0508eb4c482b9501b18e1c764d79 1bafcc2e28e444e999e02f226616f6f3 0 641595aa3a2646e9bc8ef7c12bf47e8a RX(Φ/θ) 1bafcc2e28e444e999e02f226616f6f3--641595aa3a2646e9bc8ef7c12bf47e8a 19b2f3228076444c81f95fb39819db7b 1 ec7c64db0f4b447c828c2211843d6033 641595aa3a2646e9bc8ef7c12bf47e8a--ec7c64db0f4b447c828c2211843d6033 2578a5c2eb034ef69c39f589adc09cd9 ec7c64db0f4b447c828c2211843d6033--2578a5c2eb034ef69c39f589adc09cd9 11e2cdbf10a745d79955d783deed112a HamEvo 2578a5c2eb034ef69c39f589adc09cd9--11e2cdbf10a745d79955d783deed112a 253bac4ce0184ad6a8af4142979f7194 11e2cdbf10a745d79955d783deed112a--253bac4ce0184ad6a8af4142979f7194 99f47239d54b4ad9b4e497a24286327e f02969ba5b514df58d2d07b33980eb80 RY(2*θ) 19b2f3228076444c81f95fb39819db7b--f02969ba5b514df58d2d07b33980eb80 22c221518271406aa13e005815d85edb 2 c5661fe9900c42f2bbe40061bb27798b X f02969ba5b514df58d2d07b33980eb80--c5661fe9900c42f2bbe40061bb27798b c5661fe9900c42f2bbe40061bb27798b--ec7c64db0f4b447c828c2211843d6033 e11e6fb2f3b548e591119a001c1415bd c5661fe9900c42f2bbe40061bb27798b--e11e6fb2f3b548e591119a001c1415bd 51c45da80d6b422ea9e94354ba146797 t = Φ e11e6fb2f3b548e591119a001c1415bd--51c45da80d6b422ea9e94354ba146797 51c45da80d6b422ea9e94354ba146797--99f47239d54b4ad9b4e497a24286327e f5568cce33144295ab9f9d1b2c262c84 a1a459be880b450a82729ca92f4645af RZ(cos(Φ)) 22c221518271406aa13e005815d85edb--a1a459be880b450a82729ca92f4645af ac38f85b43b441d6aef227c4d8e7600c a1a459be880b450a82729ca92f4645af--ac38f85b43b441d6aef227c4d8e7600c 6cf8d8298c75467789d604cee179bd27 PHASE(3.142) ac38f85b43b441d6aef227c4d8e7600c--6cf8d8298c75467789d604cee179bd27 6cf8d8298c75467789d604cee179bd27--e11e6fb2f3b548e591119a001c1415bd 139e1625d154420b87e7a2a6c217b2ab 6cf8d8298c75467789d604cee179bd27--139e1625d154420b87e7a2a6c217b2ab 139e1625d154420b87e7a2a6c217b2ab--f5568cce33144295ab9f9d1b2c262c84

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.