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.8880+0.0000j, 0.0000-0.4598j]])

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.0107+0.7123j, 0.0000+0.0000j, 0.7017+0.0106j, 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_507bbd9edea34c34addb3c2c694af562 1df617777c9c429380c8b00a20108179 0 1702f43a43ea468cb8e177581f11655c RX(Φ/θ) 1df617777c9c429380c8b00a20108179--1702f43a43ea468cb8e177581f11655c 0a2bc24578234b8a941ecaa519233984 1 a52af2aba3a645d28a03ccb2ac5364c6 1702f43a43ea468cb8e177581f11655c--a52af2aba3a645d28a03ccb2ac5364c6 bf453715008241aa97d2da12213196ce a52af2aba3a645d28a03ccb2ac5364c6--bf453715008241aa97d2da12213196ce a2e57bb6d89a447392b87af12cb808de HamEvo bf453715008241aa97d2da12213196ce--a2e57bb6d89a447392b87af12cb808de b5a063562c80437680706a94583907ac a2e57bb6d89a447392b87af12cb808de--b5a063562c80437680706a94583907ac 6eb9a7907a2540e1bbb098e475eb410d f7730a631fb14a9cab87984013b3a7cb RY(2*θ) 0a2bc24578234b8a941ecaa519233984--f7730a631fb14a9cab87984013b3a7cb d903264cdf0942409df482a84bcc503c 2 da689d4552a54471abd5076d7e8cc35a X f7730a631fb14a9cab87984013b3a7cb--da689d4552a54471abd5076d7e8cc35a da689d4552a54471abd5076d7e8cc35a--a52af2aba3a645d28a03ccb2ac5364c6 20ec5a87da3844e68272d6f037884c53 da689d4552a54471abd5076d7e8cc35a--20ec5a87da3844e68272d6f037884c53 44ad7057f67048d79c7e9d605c3c9b57 t = Φ 20ec5a87da3844e68272d6f037884c53--44ad7057f67048d79c7e9d605c3c9b57 44ad7057f67048d79c7e9d605c3c9b57--6eb9a7907a2540e1bbb098e475eb410d 432bf75e24c2443e859b2d2ed0a5a022 e1124af17930445cb5d9dd45fe4da238 RZ(cos(Φ)) d903264cdf0942409df482a84bcc503c--e1124af17930445cb5d9dd45fe4da238 2ff0f67e11094f0baac5d59b5f211d83 e1124af17930445cb5d9dd45fe4da238--2ff0f67e11094f0baac5d59b5f211d83 6f32d66799a04f5f978387f7b5cc6a90 PHASE(3.142) 2ff0f67e11094f0baac5d59b5f211d83--6f32d66799a04f5f978387f7b5cc6a90 6f32d66799a04f5f978387f7b5cc6a90--20ec5a87da3844e68272d6f037884c53 d34165fd9aaf4157b91b971b77c21777 6f32d66799a04f5f978387f7b5cc6a90--d34165fd9aaf4157b91b971b77c21777 d34165fd9aaf4157b91b971b77c21777--432bf75e24c2443e859b2d2ed0a5a022

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.