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.9564+0.0000j, 0.0000-0.2919j]])

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.5805-0.5678j,  0.0000+0.0000j, -0.4081-0.4173j,  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_7d0b8a712fdc48df93aaf86a8f5bab52 a91596145b004dab994c5990b14f18bb 0 c7682eb0b8294a1ca39cfccafa0be879 RX(Φ/θ) a91596145b004dab994c5990b14f18bb--c7682eb0b8294a1ca39cfccafa0be879 65686600420c49fa865613ec7989a1ab 1 8f21042e06e2442fb6591efaf071f661 c7682eb0b8294a1ca39cfccafa0be879--8f21042e06e2442fb6591efaf071f661 24cf557688764f67977b673331281574 8f21042e06e2442fb6591efaf071f661--24cf557688764f67977b673331281574 91aab10872f14deda25b534b5b3c6e2b HamEvo 24cf557688764f67977b673331281574--91aab10872f14deda25b534b5b3c6e2b 6ca1e6a97e944c3f9f29128b0359fb4e 91aab10872f14deda25b534b5b3c6e2b--6ca1e6a97e944c3f9f29128b0359fb4e 2dc75659fee54f679055edc165071ace aa8b32469e1b400ab20186c2fed7086a RY(2*θ) 65686600420c49fa865613ec7989a1ab--aa8b32469e1b400ab20186c2fed7086a e6f421ef0d4446ee958c2bea8284a208 2 da142c0512b64a679c677ce387f784f1 X aa8b32469e1b400ab20186c2fed7086a--da142c0512b64a679c677ce387f784f1 da142c0512b64a679c677ce387f784f1--8f21042e06e2442fb6591efaf071f661 7ed0baae5aeb4bf28cb52ed82c1ff705 da142c0512b64a679c677ce387f784f1--7ed0baae5aeb4bf28cb52ed82c1ff705 7b388cca6cf8475e9640046783842465 t = Φ 7ed0baae5aeb4bf28cb52ed82c1ff705--7b388cca6cf8475e9640046783842465 7b388cca6cf8475e9640046783842465--2dc75659fee54f679055edc165071ace c8f52eb0e9804b4a82acf7524aa64ec3 0e10ce47e639420db368373f5e1083bc RZ(cos(Φ)) e6f421ef0d4446ee958c2bea8284a208--0e10ce47e639420db368373f5e1083bc 0c024e34b100496a91c695aa8f8f11c3 0e10ce47e639420db368373f5e1083bc--0c024e34b100496a91c695aa8f8f11c3 fba90014235946e8a77f6dd0e0108ab0 PHASE(3.142) 0c024e34b100496a91c695aa8f8f11c3--fba90014235946e8a77f6dd0e0108ab0 fba90014235946e8a77f6dd0e0108ab0--7ed0baae5aeb4bf28cb52ed82c1ff705 4e997eb91cae4fc4bf8312b8a69f95a1 fba90014235946e8a77f6dd0e0108ab0--4e997eb91cae4fc4bf8312b8a69f95a1 4e997eb91cae4fc4bf8312b8a69f95a1--c8f52eb0e9804b4a82acf7524aa64ec3

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.