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.9342+0.0000j, 0.0000-0.3567j]])

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.1615+0.9483j,  0.0000+0.0000j,  0.2694-0.0459j,  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_d02a4ea866dc46398b134a598fead779 f6f6e7d39f494d5e9742707c74069f15 0 f654db8ce7454fa183db91697ccce5bd RX(Φ/θ) f6f6e7d39f494d5e9742707c74069f15--f654db8ce7454fa183db91697ccce5bd 4604728b4d2942b2bd608d1e90b52ce5 1 4b00d12d09a649d39f18173758a8084c f654db8ce7454fa183db91697ccce5bd--4b00d12d09a649d39f18173758a8084c 404826cd364b4c68b8aaa6b7888f443c 4b00d12d09a649d39f18173758a8084c--404826cd364b4c68b8aaa6b7888f443c e4a33e72de4148ebb5b3c0ae3bfd0b87 HamEvo 404826cd364b4c68b8aaa6b7888f443c--e4a33e72de4148ebb5b3c0ae3bfd0b87 94517c7e6d0f4edb9648158077773967 e4a33e72de4148ebb5b3c0ae3bfd0b87--94517c7e6d0f4edb9648158077773967 7e8bd7a07577409aaa60e17d996aade2 cde36d68039f48248e7b61ee4828fabf RY(2*θ) 4604728b4d2942b2bd608d1e90b52ce5--cde36d68039f48248e7b61ee4828fabf 25f45e6b96af455d92bbc97960cd5fef 2 01714220953a4dcf9ef1b5bd1ecb058e X cde36d68039f48248e7b61ee4828fabf--01714220953a4dcf9ef1b5bd1ecb058e 01714220953a4dcf9ef1b5bd1ecb058e--4b00d12d09a649d39f18173758a8084c a35d6eaa50c0474ea39433b469343c58 01714220953a4dcf9ef1b5bd1ecb058e--a35d6eaa50c0474ea39433b469343c58 6668298443aa480aa080c67b7ba030bd t = Φ a35d6eaa50c0474ea39433b469343c58--6668298443aa480aa080c67b7ba030bd 6668298443aa480aa080c67b7ba030bd--7e8bd7a07577409aaa60e17d996aade2 66a295dd2eb44e15aa8c6b0d8ab4002c ad457513fa104649b33516a25116f122 RZ(cos(Φ)) 25f45e6b96af455d92bbc97960cd5fef--ad457513fa104649b33516a25116f122 d1d9e3924cb64b37b8704540da1ec67a ad457513fa104649b33516a25116f122--d1d9e3924cb64b37b8704540da1ec67a 05f91a6232b7435da8eb8174b7647910 PHASE(3.142) d1d9e3924cb64b37b8704540da1ec67a--05f91a6232b7435da8eb8174b7647910 05f91a6232b7435da8eb8174b7647910--a35d6eaa50c0474ea39433b469343c58 b976c47b62a14e6387ba271b196f1f79 05f91a6232b7435da8eb8174b7647910--b976c47b62a14e6387ba271b196f1f79 b976c47b62a14e6387ba271b196f1f79--66a295dd2eb44e15aa8c6b0d8ab4002c

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.