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.9983+0.0000j, 0.0000-0.0577j]])

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.1917+0.9412j,  0.0000+0.0000j,  0.2727-0.0555j,  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_848bb54ce12e4a2998df835c62b06c9e a5004b4a500c451fbfe9016138bba6bb 0 2c26ae4002684274a46a2844cd706f9d RX(Φ/θ) a5004b4a500c451fbfe9016138bba6bb--2c26ae4002684274a46a2844cd706f9d ff8ef7272a524bbc93050669e948205f 1 e7ab64db31554996af62a575d4752d52 2c26ae4002684274a46a2844cd706f9d--e7ab64db31554996af62a575d4752d52 e4ab8bfc06f541e38be2b3ee538a72fa e7ab64db31554996af62a575d4752d52--e4ab8bfc06f541e38be2b3ee538a72fa bcb56f6cfbc24958a861d52718035516 HamEvo e4ab8bfc06f541e38be2b3ee538a72fa--bcb56f6cfbc24958a861d52718035516 39353d2ec6c8461d9bbe3e0287d43e1b bcb56f6cfbc24958a861d52718035516--39353d2ec6c8461d9bbe3e0287d43e1b cc0cd6c4504b49089000ea3a41108982 a8bcb739092f42ff87bc3cf0342d6e49 RY(2*θ) ff8ef7272a524bbc93050669e948205f--a8bcb739092f42ff87bc3cf0342d6e49 7a56448e05ef410e8e9dab6b3deb5809 2 dadaf61440914e4ba93b61f8ef669118 X a8bcb739092f42ff87bc3cf0342d6e49--dadaf61440914e4ba93b61f8ef669118 dadaf61440914e4ba93b61f8ef669118--e7ab64db31554996af62a575d4752d52 61ca0bf5f35f4bd0bd6b64ef380d9e49 dadaf61440914e4ba93b61f8ef669118--61ca0bf5f35f4bd0bd6b64ef380d9e49 3af60921888f4fff92a39f8f4978f614 t = Φ 61ca0bf5f35f4bd0bd6b64ef380d9e49--3af60921888f4fff92a39f8f4978f614 3af60921888f4fff92a39f8f4978f614--cc0cd6c4504b49089000ea3a41108982 ea35408db38c4f579eb8b384ce66b9bf fde6070337ed4dc3b463db18c6f980bf RZ(cos(Φ)) 7a56448e05ef410e8e9dab6b3deb5809--fde6070337ed4dc3b463db18c6f980bf 23055569f0354c61a8d6a029532b05e0 fde6070337ed4dc3b463db18c6f980bf--23055569f0354c61a8d6a029532b05e0 c8b3ae1f78e1498a8128aa173f52b50e PHASE(3.142) 23055569f0354c61a8d6a029532b05e0--c8b3ae1f78e1498a8128aa173f52b50e c8b3ae1f78e1498a8128aa173f52b50e--61ca0bf5f35f4bd0bd6b64ef380d9e49 0a0053932e2d4b2aa10e47b3a166898a c8b3ae1f78e1498a8128aa173f52b50e--0a0053932e2d4b2aa10e47b3a166898a 0a0053932e2d4b2aa10e47b3a166898a--ea35408db38c4f579eb8b384ce66b9bf

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.