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.9975+0.0000j, 0.0000-0.0713j]])

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.8621+0.2529j,  0.0000+0.0000j,  0.1236-0.4213j,  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_4d8caecaec004cd59dbde20b7db2084f f32592978ca54b13a86f572ccdadb48b 0 d235723e27cc49108098074f96a287aa RX(Φ/θ) f32592978ca54b13a86f572ccdadb48b--d235723e27cc49108098074f96a287aa 1a9578dd33634691809e02798811af1b 1 7059133f826144d08861bc49edf7e21a d235723e27cc49108098074f96a287aa--7059133f826144d08861bc49edf7e21a 8363c473220a43e2879f4d4bb23b1a04 7059133f826144d08861bc49edf7e21a--8363c473220a43e2879f4d4bb23b1a04 965f1f5b829b47eabdd054e914389fef HamEvo 8363c473220a43e2879f4d4bb23b1a04--965f1f5b829b47eabdd054e914389fef 891e69f49776400cbdcf63977536d4c4 965f1f5b829b47eabdd054e914389fef--891e69f49776400cbdcf63977536d4c4 1694d8eaa87e4c24b3afc6a55f188f69 4cd62ef2a36c46ab982ed8f9f317e5a5 RY(2*θ) 1a9578dd33634691809e02798811af1b--4cd62ef2a36c46ab982ed8f9f317e5a5 422f8e17a7c4471385320761f7e9f3e4 2 f8cdb96a12b8434890c4223b54948bc0 X 4cd62ef2a36c46ab982ed8f9f317e5a5--f8cdb96a12b8434890c4223b54948bc0 f8cdb96a12b8434890c4223b54948bc0--7059133f826144d08861bc49edf7e21a 5f4b1b93ded5439f83ee4c9646d7116e f8cdb96a12b8434890c4223b54948bc0--5f4b1b93ded5439f83ee4c9646d7116e ed4e0a39702245e4b07024a94e8056fe t = Φ 5f4b1b93ded5439f83ee4c9646d7116e--ed4e0a39702245e4b07024a94e8056fe ed4e0a39702245e4b07024a94e8056fe--1694d8eaa87e4c24b3afc6a55f188f69 1892e82f13e04515ab9b38a3bb778012 391ef6ee9a1f4259a412ccb0c0101131 RZ(cos(Φ)) 422f8e17a7c4471385320761f7e9f3e4--391ef6ee9a1f4259a412ccb0c0101131 d03e47820baf4a18830e114f338c241c 391ef6ee9a1f4259a412ccb0c0101131--d03e47820baf4a18830e114f338c241c b9dd0effd1f34c8d87ad871a56765ee4 PHASE(3.142) d03e47820baf4a18830e114f338c241c--b9dd0effd1f34c8d87ad871a56765ee4 b9dd0effd1f34c8d87ad871a56765ee4--5f4b1b93ded5439f83ee4c9646d7116e 8c36d288300e43f280101d27a8cf68c3 b9dd0effd1f34c8d87ad871a56765ee4--8c36d288300e43f280101d27a8cf68c3 8c36d288300e43f280101d27a8cf68c3--1892e82f13e04515ab9b38a3bb778012

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.