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.9994+0.0000j, 0.0000-0.0343j]])

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.4081-0.5118j,  0.0000+0.0000j, -0.5911+0.4713j,  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_6c1750ea25fe4207afe7474929910b48 56c2bf22604746ddb890915d30c8f7f3 0 32c7242df8aa4487821abc28220a9982 RX(Φ/θ) 56c2bf22604746ddb890915d30c8f7f3--32c7242df8aa4487821abc28220a9982 74b1c3ec04cb4fc7b1273c4381de3134 1 240c28f4b9924609a4ee500241253de5 32c7242df8aa4487821abc28220a9982--240c28f4b9924609a4ee500241253de5 c056e3fe0c9647b7b2e62683dc6b8b71 240c28f4b9924609a4ee500241253de5--c056e3fe0c9647b7b2e62683dc6b8b71 526a8e23f3d3496c8425ea2b931a5761 HamEvo c056e3fe0c9647b7b2e62683dc6b8b71--526a8e23f3d3496c8425ea2b931a5761 b230b46380be495ca1df78f1b7b66896 526a8e23f3d3496c8425ea2b931a5761--b230b46380be495ca1df78f1b7b66896 732b40b4fb9245358380c05ac7da9269 60fe8473dc0344fc9b497abb6e351fec RY(2*θ) 74b1c3ec04cb4fc7b1273c4381de3134--60fe8473dc0344fc9b497abb6e351fec 0d572ce4a8064322b6c6ca2795c7714c 2 276a91b2c5ff43188dc7df200e642676 X 60fe8473dc0344fc9b497abb6e351fec--276a91b2c5ff43188dc7df200e642676 276a91b2c5ff43188dc7df200e642676--240c28f4b9924609a4ee500241253de5 ef78c2335b0a4819bcad000efb5ba7cc 276a91b2c5ff43188dc7df200e642676--ef78c2335b0a4819bcad000efb5ba7cc 2767f330ffa44ca0ad7128e29101019a t = Φ ef78c2335b0a4819bcad000efb5ba7cc--2767f330ffa44ca0ad7128e29101019a 2767f330ffa44ca0ad7128e29101019a--732b40b4fb9245358380c05ac7da9269 c6c3fcc553084d8aa5f8c269f7103410 ef9d2fdc3db74da9af69ee893031269a RZ(cos(Φ)) 0d572ce4a8064322b6c6ca2795c7714c--ef9d2fdc3db74da9af69ee893031269a 5c05143d7af64924a44e7ae4c6849e97 ef9d2fdc3db74da9af69ee893031269a--5c05143d7af64924a44e7ae4c6849e97 5b43033b3b304cfeb36a0f33d70d07f5 PHASE(3.142) 5c05143d7af64924a44e7ae4c6849e97--5b43033b3b304cfeb36a0f33d70d07f5 5b43033b3b304cfeb36a0f33d70d07f5--ef78c2335b0a4819bcad000efb5ba7cc 6b65635739a942299990bad4691bc2d1 5b43033b3b304cfeb36a0f33d70d07f5--6b65635739a942299990bad4691bc2d1 6b65635739a942299990bad4691bc2d1--c6c3fcc553084d8aa5f8c269f7103410

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.