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.9520+0.0000j, 0.0000-0.3060j]])

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, 1.0), values = {"phi": tensor(PI)})
wf = tensor([[0.6752+0.6383j, 0.0000+0.0000j, 0.2539+0.2686j, 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_2482cd8c3bd2472198608a52ae60f30a af231fe1e09c45ad8f1176b1cbce6015 0 1041971feba5498ebbc73b7424e4af3e RX(Φ/θ) af231fe1e09c45ad8f1176b1cbce6015--1041971feba5498ebbc73b7424e4af3e 4522d88caf724292970d16b57f047670 1 744fd5e8d8aa4dd594fb699a764beaa0 1041971feba5498ebbc73b7424e4af3e--744fd5e8d8aa4dd594fb699a764beaa0 de44e10c741e4be9a7120ec22dce1030 744fd5e8d8aa4dd594fb699a764beaa0--de44e10c741e4be9a7120ec22dce1030 4155d4d3d8bc4eb89407d4dd931f1cc8 HamEvo de44e10c741e4be9a7120ec22dce1030--4155d4d3d8bc4eb89407d4dd931f1cc8 08ccf373cbaa4f589851119441506a9f 4155d4d3d8bc4eb89407d4dd931f1cc8--08ccf373cbaa4f589851119441506a9f f37dd9dbadee418f895082707c1df198 bda4050b732c4841bd2b069c53b71ce2 RY(2*θ) 4522d88caf724292970d16b57f047670--bda4050b732c4841bd2b069c53b71ce2 bd9b5c10640040c68457452d35867c24 2 44306b35f38b423f82a8ce7025d4b1e1 X bda4050b732c4841bd2b069c53b71ce2--44306b35f38b423f82a8ce7025d4b1e1 44306b35f38b423f82a8ce7025d4b1e1--744fd5e8d8aa4dd594fb699a764beaa0 9b12a26c58104e9cb465214f14b4d280 44306b35f38b423f82a8ce7025d4b1e1--9b12a26c58104e9cb465214f14b4d280 de9675d999d44fb8935de648f25fdc14 t = Φ 9b12a26c58104e9cb465214f14b4d280--de9675d999d44fb8935de648f25fdc14 de9675d999d44fb8935de648f25fdc14--f37dd9dbadee418f895082707c1df198 14cc0991d30843f1ba79d3d54e5dd4c5 23c0f6bddddc4ea3b73d5f71a7d89d0a RZ(cos(Φ)) bd9b5c10640040c68457452d35867c24--23c0f6bddddc4ea3b73d5f71a7d89d0a ae6a0c4eb0074cb487f46b08550a1029 23c0f6bddddc4ea3b73d5f71a7d89d0a--ae6a0c4eb0074cb487f46b08550a1029 d227084cceeb4ce18b6d50a18987445f PHASE(3.142) ae6a0c4eb0074cb487f46b08550a1029--d227084cceeb4ce18b6d50a18987445f d227084cceeb4ce18b6d50a18987445f--9b12a26c58104e9cb465214f14b4d280 328fb4099ac24a4e9b9d5715dadaf4f2 d227084cceeb4ce18b6d50a18987445f--328fb4099ac24a4e9b9d5715dadaf4f2 328fb4099ac24a4e9b9d5715dadaf4f2--14cc0991d30843f1ba79d3d54e5dd4c5

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.