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.9267+0.0000j, 0.0000-0.3758j]])

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.7315-0.4051j,  0.0000+0.0000j, -0.2657-0.4798j,  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_73ae2005c0354d348769fce8a5d5f160 d6cb3ac726cf4973ab7c47fbfb29534c 0 f475af5cddea4fb6894e727b27c40c70 RX(Φ/θ) d6cb3ac726cf4973ab7c47fbfb29534c--f475af5cddea4fb6894e727b27c40c70 142ddbb1b80747058c7e01bc67849eef 1 910f6678c6e54d5fb6fe035a4dd73cff f475af5cddea4fb6894e727b27c40c70--910f6678c6e54d5fb6fe035a4dd73cff 7db2c9940e23495e9c95d2998fa7c363 910f6678c6e54d5fb6fe035a4dd73cff--7db2c9940e23495e9c95d2998fa7c363 f7b13717e84148f1b87844433be586e9 HamEvo 7db2c9940e23495e9c95d2998fa7c363--f7b13717e84148f1b87844433be586e9 4c2333b0c7294d4f871ebe3ef3e430f7 f7b13717e84148f1b87844433be586e9--4c2333b0c7294d4f871ebe3ef3e430f7 1261af2717694df088a26a9af2e2256b 6cd7f06051144ef4ba220b720bdbecd4 RY(2*θ) 142ddbb1b80747058c7e01bc67849eef--6cd7f06051144ef4ba220b720bdbecd4 4dc5d7c1f85f4e72bb6381af78deb95f 2 533263ca2735458883ddb36687404cb7 X 6cd7f06051144ef4ba220b720bdbecd4--533263ca2735458883ddb36687404cb7 533263ca2735458883ddb36687404cb7--910f6678c6e54d5fb6fe035a4dd73cff 225cfb99031e402c9a1012f41abb87b9 533263ca2735458883ddb36687404cb7--225cfb99031e402c9a1012f41abb87b9 b9e2e8ddfef440a2b86ed5d6f92adc1b t = Φ 225cfb99031e402c9a1012f41abb87b9--b9e2e8ddfef440a2b86ed5d6f92adc1b b9e2e8ddfef440a2b86ed5d6f92adc1b--1261af2717694df088a26a9af2e2256b 7d463a474dc04653abc6db99114e3296 476a6a9dd7664674920aa0d1bf9dd2d2 RZ(cos(Φ)) 4dc5d7c1f85f4e72bb6381af78deb95f--476a6a9dd7664674920aa0d1bf9dd2d2 4dec6bcc40894349872e385e97ddac09 476a6a9dd7664674920aa0d1bf9dd2d2--4dec6bcc40894349872e385e97ddac09 97d58a735a8943299ab5a282526080d5 PHASE(3.142) 4dec6bcc40894349872e385e97ddac09--97d58a735a8943299ab5a282526080d5 97d58a735a8943299ab5a282526080d5--225cfb99031e402c9a1012f41abb87b9 ed4c5735aba544428f7cd9383a973b4d 97d58a735a8943299ab5a282526080d5--ed4c5735aba544428f7cd9383a973b4d ed4c5735aba544428f7cd9383a973b4d--7d463a474dc04653abc6db99114e3296

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.