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.9246+0.0000j, 0.0000-0.3809j]])

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.2384+0.1550j,  0.0000+0.0000j,  0.5227-0.8037j,  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_bc524c76d0c849fb971fca81eec7f267 481c97bb6e1b4ae6880f4cab5a925668 0 01fafb5cb33246098f8f916a32991c9d RX(Φ/θ) 481c97bb6e1b4ae6880f4cab5a925668--01fafb5cb33246098f8f916a32991c9d 124f79ca37814389a6e21b0bb505a6b8 1 f1b501ac667942649b01823fa570a229 01fafb5cb33246098f8f916a32991c9d--f1b501ac667942649b01823fa570a229 636184fd56314b91a56ac40009e61da6 f1b501ac667942649b01823fa570a229--636184fd56314b91a56ac40009e61da6 6e5595497c18450bb4226eb49f591b5d HamEvo 636184fd56314b91a56ac40009e61da6--6e5595497c18450bb4226eb49f591b5d 2dda9c0e840c482193f53bc4a95d3ff2 6e5595497c18450bb4226eb49f591b5d--2dda9c0e840c482193f53bc4a95d3ff2 391f5f81ccc6478ea140a0827d5ddc2e 7a8aa8dba41348e1a915c2f7d5462489 RY(2*θ) 124f79ca37814389a6e21b0bb505a6b8--7a8aa8dba41348e1a915c2f7d5462489 3783f9a73d28460e97277993801f7b3e 2 953a8485a14a409fbe2db1f3ccc8d83e X 7a8aa8dba41348e1a915c2f7d5462489--953a8485a14a409fbe2db1f3ccc8d83e 953a8485a14a409fbe2db1f3ccc8d83e--f1b501ac667942649b01823fa570a229 2c4501286bd548af992c675f0a56d46d 953a8485a14a409fbe2db1f3ccc8d83e--2c4501286bd548af992c675f0a56d46d c29cb8921073454598b75801542c8e18 t = Φ 2c4501286bd548af992c675f0a56d46d--c29cb8921073454598b75801542c8e18 c29cb8921073454598b75801542c8e18--391f5f81ccc6478ea140a0827d5ddc2e 35e2c603687e4d15b7756bb63e9f4621 07a6fbe156f84b19ad47d16dfbae9ff4 RZ(cos(Φ)) 3783f9a73d28460e97277993801f7b3e--07a6fbe156f84b19ad47d16dfbae9ff4 43d85feaf2f846969cd0ab107067edf9 07a6fbe156f84b19ad47d16dfbae9ff4--43d85feaf2f846969cd0ab107067edf9 090b5d1893ec443f9996bc0ba31fa00c PHASE(3.142) 43d85feaf2f846969cd0ab107067edf9--090b5d1893ec443f9996bc0ba31fa00c 090b5d1893ec443f9996bc0ba31fa00c--2c4501286bd548af992c675f0a56d46d 373d87b6098e4397ac8a585232ac08e9 090b5d1893ec443f9996bc0ba31fa00c--373d87b6098e4397ac8a585232ac08e9 373d87b6098e4397ac8a585232ac08e9--35e2c603687e4d15b7756bb63e9f4621

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.