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.9904+0.0000j, 0.0000-0.1381j]])

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.2397-0.6494j,  0.0000+0.0000j, -0.6771+0.2499j,  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_1457d00722a94043a1e3bea61a5ad300 5fcf896e068d4e5b8d05bf53e68e0e65 0 cf49332fcd3e4a8f99522962a45ecc38 RX(Φ/θ) 5fcf896e068d4e5b8d05bf53e68e0e65--cf49332fcd3e4a8f99522962a45ecc38 43ba74edd31543be8aa155e14656199e 1 5d41c5d9640c43688f548442f987fee3 cf49332fcd3e4a8f99522962a45ecc38--5d41c5d9640c43688f548442f987fee3 3069f15c15da4ae7a9a091d6f8b8c3cf 5d41c5d9640c43688f548442f987fee3--3069f15c15da4ae7a9a091d6f8b8c3cf f1db1e10c89e47a6863c4d4c0fd264fa HamEvo 3069f15c15da4ae7a9a091d6f8b8c3cf--f1db1e10c89e47a6863c4d4c0fd264fa 0f7c444dca834c9fb63afec0f2c4b744 f1db1e10c89e47a6863c4d4c0fd264fa--0f7c444dca834c9fb63afec0f2c4b744 a97ffc79679e499da0f9bf63a71469af 8e90bdfc288e46a5a08f136fec39e637 RY(2*θ) 43ba74edd31543be8aa155e14656199e--8e90bdfc288e46a5a08f136fec39e637 0c6baab680a140f1a39a98823e9a78e1 2 e64f625303c844a3bea2bd6ed75cc74d X 8e90bdfc288e46a5a08f136fec39e637--e64f625303c844a3bea2bd6ed75cc74d e64f625303c844a3bea2bd6ed75cc74d--5d41c5d9640c43688f548442f987fee3 f2a83559548f487aa2d6749dce39473e e64f625303c844a3bea2bd6ed75cc74d--f2a83559548f487aa2d6749dce39473e 10c6db9ca66e4f969e37b428e0959fd2 t = Φ f2a83559548f487aa2d6749dce39473e--10c6db9ca66e4f969e37b428e0959fd2 10c6db9ca66e4f969e37b428e0959fd2--a97ffc79679e499da0f9bf63a71469af 724ba59045e248479a668ce5e9085b97 3884f6e6464c4d05905cd4ed8ce45bea RZ(cos(Φ)) 0c6baab680a140f1a39a98823e9a78e1--3884f6e6464c4d05905cd4ed8ce45bea 6dfedfe5b61248d5a531f14012b21673 3884f6e6464c4d05905cd4ed8ce45bea--6dfedfe5b61248d5a531f14012b21673 836096b5bd4d4bcabe282a4abe72aa22 PHASE(3.142) 6dfedfe5b61248d5a531f14012b21673--836096b5bd4d4bcabe282a4abe72aa22 836096b5bd4d4bcabe282a4abe72aa22--f2a83559548f487aa2d6749dce39473e 7c8c205f71fe433da5a389083a58e47a 836096b5bd4d4bcabe282a4abe72aa22--7c8c205f71fe433da5a389083a58e47a 7c8c205f71fe433da5a389083a58e47a--724ba59045e248479a668ce5e9085b97

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.