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.9028+0.0000j, 0.0000-0.4300j]])

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.5878-0.3413j,  0.0000+0.0000j, -0.3682-0.6343j,  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_14b8b6cc8ef649e0b09576d77b2b6515 78f0ca3d8d3848d9af9754cabd3b8077 0 c45dbcdae1d04e989c52e26a2a2cafcc RX(Φ/θ) 78f0ca3d8d3848d9af9754cabd3b8077--c45dbcdae1d04e989c52e26a2a2cafcc 994dd4808c8a4f54a03f8ac23407aede 1 25b13a265a6f41d384a4c8fb1d22ffb6 c45dbcdae1d04e989c52e26a2a2cafcc--25b13a265a6f41d384a4c8fb1d22ffb6 26035cb1d8774f85bdd0de45808c590b 25b13a265a6f41d384a4c8fb1d22ffb6--26035cb1d8774f85bdd0de45808c590b 7a913e9e2f454100b897a01f89a29681 HamEvo 26035cb1d8774f85bdd0de45808c590b--7a913e9e2f454100b897a01f89a29681 91e818fca57e4e878c663df394942f1b 7a913e9e2f454100b897a01f89a29681--91e818fca57e4e878c663df394942f1b ca2c9d64063542819ffc7658948519d6 50d962c75ace4507b1608095287e8c84 RY(2*θ) 994dd4808c8a4f54a03f8ac23407aede--50d962c75ace4507b1608095287e8c84 9c8fd5bea6bf4911a62cd5cab78a4998 2 62b60da91de6455e83ba67745a4ef485 X 50d962c75ace4507b1608095287e8c84--62b60da91de6455e83ba67745a4ef485 62b60da91de6455e83ba67745a4ef485--25b13a265a6f41d384a4c8fb1d22ffb6 48902869e2174421965343d297ec7ee0 62b60da91de6455e83ba67745a4ef485--48902869e2174421965343d297ec7ee0 de1805c4985146268fe36c6baa8eeda1 t = Φ 48902869e2174421965343d297ec7ee0--de1805c4985146268fe36c6baa8eeda1 de1805c4985146268fe36c6baa8eeda1--ca2c9d64063542819ffc7658948519d6 7b2b3e2440804eadb9bbb24aaf19f062 a862fcab6cb14ce0b1ad552306ec1598 RZ(cos(Φ)) 9c8fd5bea6bf4911a62cd5cab78a4998--a862fcab6cb14ce0b1ad552306ec1598 88b94c0341db46bc909d9daa1e18fe3a a862fcab6cb14ce0b1ad552306ec1598--88b94c0341db46bc909d9daa1e18fe3a 6ade2b787f5b4e6bb60ff0a0b506bc80 PHASE(3.142) 88b94c0341db46bc909d9daa1e18fe3a--6ade2b787f5b4e6bb60ff0a0b506bc80 6ade2b787f5b4e6bb60ff0a0b506bc80--48902869e2174421965343d297ec7ee0 824c41dca4ab4e398eb74474dae53c3c 6ade2b787f5b4e6bb60ff0a0b506bc80--824c41dca4ab4e398eb74474dae53c3c 824c41dca4ab4e398eb74474dae53c3c--7b2b3e2440804eadb9bbb24aaf19f062

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.