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.9370+0.0000j, 0.0000-0.3493j]])

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.0079+0.3190j, 0.0000+0.0000j, 0.9474+0.0235j, 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_4c611b594fac4fe6b611e2cb8de28f42 9617ebc10112429abb1aad86c7b8d541 0 8d6160f4f31e460387bb50ae935c2e2a RX(Φ/θ) 9617ebc10112429abb1aad86c7b8d541--8d6160f4f31e460387bb50ae935c2e2a 4305b13ed04d4f6d8bc9876fdb0b985c 1 6f66679da304401ea9eb8c5b4ba69e5d 8d6160f4f31e460387bb50ae935c2e2a--6f66679da304401ea9eb8c5b4ba69e5d f27abe2af4d543fa96458e2bb667ecb9 6f66679da304401ea9eb8c5b4ba69e5d--f27abe2af4d543fa96458e2bb667ecb9 47252d27f2f2437dbf0fd135f2b94612 HamEvo f27abe2af4d543fa96458e2bb667ecb9--47252d27f2f2437dbf0fd135f2b94612 68596cac29284ec6acc6d39b2c34094a 47252d27f2f2437dbf0fd135f2b94612--68596cac29284ec6acc6d39b2c34094a 455e3179eb79455cb988855b3fe3f3e7 0bf8d3301c084787bf41f9db91ff6929 RY(2*θ) 4305b13ed04d4f6d8bc9876fdb0b985c--0bf8d3301c084787bf41f9db91ff6929 2e1fdb84403441198c0d52b8b4158324 2 425c40d7b75840b481a1d24e5ac95005 X 0bf8d3301c084787bf41f9db91ff6929--425c40d7b75840b481a1d24e5ac95005 425c40d7b75840b481a1d24e5ac95005--6f66679da304401ea9eb8c5b4ba69e5d c7cdf80e1c1b40b4a7d8dd278f557f58 425c40d7b75840b481a1d24e5ac95005--c7cdf80e1c1b40b4a7d8dd278f557f58 4deabf97495849649e4111f9aaff6e44 t = Φ c7cdf80e1c1b40b4a7d8dd278f557f58--4deabf97495849649e4111f9aaff6e44 4deabf97495849649e4111f9aaff6e44--455e3179eb79455cb988855b3fe3f3e7 8e76269895b84e9cbf3c6e172fa340aa 426d3d51202242698371b3a34dede969 RZ(cos(Φ)) 2e1fdb84403441198c0d52b8b4158324--426d3d51202242698371b3a34dede969 a86f85dc4b5341c6b27f68f773ec3c5e 426d3d51202242698371b3a34dede969--a86f85dc4b5341c6b27f68f773ec3c5e ff1bb0c7134443e1b516fa38b1b71caf PHASE(3.142) a86f85dc4b5341c6b27f68f773ec3c5e--ff1bb0c7134443e1b516fa38b1b71caf ff1bb0c7134443e1b516fa38b1b71caf--c7cdf80e1c1b40b4a7d8dd278f557f58 053ac622a11c4fcc86e3631c4545cd00 ff1bb0c7134443e1b516fa38b1b71caf--053ac622a11c4fcc86e3631c4545cd00 053ac622a11c4fcc86e3631c4545cd00--8e76269895b84e9cbf3c6e172fa340aa

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.