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.9773+0.0000j, 0.0000-0.2116j]])

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.4014+0.2382j, 0.0000+0.0000j, 0.4513+0.7606j, 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_2b770bbbb8034e168cf2a1fbf7899193 021531a974e84e7d9f0ce37abb514cb0 0 839cac92acce4e67a7ca0591059ecc54 RX(Φ/θ) 021531a974e84e7d9f0ce37abb514cb0--839cac92acce4e67a7ca0591059ecc54 6bcfe458064c4380be992d5f5fc684a2 1 775e9d3f86da49ae9982d5a657d9d278 839cac92acce4e67a7ca0591059ecc54--775e9d3f86da49ae9982d5a657d9d278 f3097a5786844a158828f24f74d91580 775e9d3f86da49ae9982d5a657d9d278--f3097a5786844a158828f24f74d91580 98047224eb364d679d409e312df2f809 HamEvo f3097a5786844a158828f24f74d91580--98047224eb364d679d409e312df2f809 7cc18238e6a641f293dde18af58ec4c3 98047224eb364d679d409e312df2f809--7cc18238e6a641f293dde18af58ec4c3 180a0fa90b2240fc8f799fea0343ffcb d7f996be0ecc4307a65abf0095b80760 RY(2*θ) 6bcfe458064c4380be992d5f5fc684a2--d7f996be0ecc4307a65abf0095b80760 87304becf7264e7ead79537dececb715 2 8d2df63c6a314e0490728b10a0cf59a9 X d7f996be0ecc4307a65abf0095b80760--8d2df63c6a314e0490728b10a0cf59a9 8d2df63c6a314e0490728b10a0cf59a9--775e9d3f86da49ae9982d5a657d9d278 648eb0876bdb44879ac335af2f75e38d 8d2df63c6a314e0490728b10a0cf59a9--648eb0876bdb44879ac335af2f75e38d ad21fe41e02d44de84491a9a25c50ecb t = Φ 648eb0876bdb44879ac335af2f75e38d--ad21fe41e02d44de84491a9a25c50ecb ad21fe41e02d44de84491a9a25c50ecb--180a0fa90b2240fc8f799fea0343ffcb bd4194573d804391985a0f1fcad4686f 581c70e545744760b13eda62743a9c84 RZ(cos(Φ)) 87304becf7264e7ead79537dececb715--581c70e545744760b13eda62743a9c84 d4aacc0f261142ec994c82866ca63823 581c70e545744760b13eda62743a9c84--d4aacc0f261142ec994c82866ca63823 f18d218edf334dabb406ab649a39758d PHASE(3.142) d4aacc0f261142ec994c82866ca63823--f18d218edf334dabb406ab649a39758d f18d218edf334dabb406ab649a39758d--648eb0876bdb44879ac335af2f75e38d 83e1ff653c04442d952eff9bd950b2fa f18d218edf334dabb406ab649a39758d--83e1ff653c04442d952eff9bd950b2fa 83e1ff653c04442d952eff9bd950b2fa--bd4194573d804391985a0f1fcad4686f

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.