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

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.1774+0.9594j, 0.0000+0.0000j, 0.2155+0.0398j, 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_848314d5d9f5470c8979d2f76002ed91 f791d75fbcba497381251f375f0671a6 0 c20b9659136c4ff285f8aab5cbd872d0 RX(Φ/θ) f791d75fbcba497381251f375f0671a6--c20b9659136c4ff285f8aab5cbd872d0 2b0bca4b4d7342a1822590766fc7b0c2 1 7754f06644ce486a98cad4308080784d c20b9659136c4ff285f8aab5cbd872d0--7754f06644ce486a98cad4308080784d afb2792b49d64181b3cfec1c005d6180 7754f06644ce486a98cad4308080784d--afb2792b49d64181b3cfec1c005d6180 b5f492558322481f80e57565b218ca3e HamEvo afb2792b49d64181b3cfec1c005d6180--b5f492558322481f80e57565b218ca3e bc3177e517064db9a58ab70ec94a46d0 b5f492558322481f80e57565b218ca3e--bc3177e517064db9a58ab70ec94a46d0 45d3b2a36b80425da07df501eecb7df0 5e723442aff64ed99dcbefda3f711baf RY(2*θ) 2b0bca4b4d7342a1822590766fc7b0c2--5e723442aff64ed99dcbefda3f711baf 9ed6decedf4e4b878d78ea188f1d8ba3 2 d2990ea4a63148d89c99944bc1dd4e85 X 5e723442aff64ed99dcbefda3f711baf--d2990ea4a63148d89c99944bc1dd4e85 d2990ea4a63148d89c99944bc1dd4e85--7754f06644ce486a98cad4308080784d 1fd84b51539e40ee940e061738a1c251 d2990ea4a63148d89c99944bc1dd4e85--1fd84b51539e40ee940e061738a1c251 23868d264b9e4884a0a5470e1e5760bf t = Φ 1fd84b51539e40ee940e061738a1c251--23868d264b9e4884a0a5470e1e5760bf 23868d264b9e4884a0a5470e1e5760bf--45d3b2a36b80425da07df501eecb7df0 f6178a2cf444433a93a06c568cf9acc2 4151dee6e9674538acaabaa3fa31b07e RZ(cos(Φ)) 9ed6decedf4e4b878d78ea188f1d8ba3--4151dee6e9674538acaabaa3fa31b07e 39c44ade6f1848a4917052346eda139b 4151dee6e9674538acaabaa3fa31b07e--39c44ade6f1848a4917052346eda139b 19f1d31b5c054de0a2d13aba4ee9da24 PHASE(3.142) 39c44ade6f1848a4917052346eda139b--19f1d31b5c054de0a2d13aba4ee9da24 19f1d31b5c054de0a2d13aba4ee9da24--1fd84b51539e40ee940e061738a1c251 c3d39afab2804440890b111026e60a97 19f1d31b5c054de0a2d13aba4ee9da24--c3d39afab2804440890b111026e60a97 c3d39afab2804440890b111026e60a97--f6178a2cf444433a93a06c568cf9acc2

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.