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.9599+0.0000j, 0.0000-0.2804j]])

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, 1.0), values = {"phi": tensor(PI)})
wf = tensor([[-0.2707+0.3371j,  0.0000+0.0000j,  0.7031-0.5645j,  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_d9c1588ac8d247daae1cd1d390899912 384c5c51a402401ba8561bff932a16f6 0 7c2ed688adbe400cbb70a077f74c8d7e RX(Φ/θ) 384c5c51a402401ba8561bff932a16f6--7c2ed688adbe400cbb70a077f74c8d7e 6e87f4f279254b0b87317099abce9788 1 1d135a8203dd41dbba3ecd6555aac966 7c2ed688adbe400cbb70a077f74c8d7e--1d135a8203dd41dbba3ecd6555aac966 e45d743a3e4a46a8998c91bde489de37 1d135a8203dd41dbba3ecd6555aac966--e45d743a3e4a46a8998c91bde489de37 dd697f3514f44a59a273f7098807d9ce HamEvo e45d743a3e4a46a8998c91bde489de37--dd697f3514f44a59a273f7098807d9ce a73897d7e7db4bcfab77e9d3623db423 dd697f3514f44a59a273f7098807d9ce--a73897d7e7db4bcfab77e9d3623db423 5b45527977304d759347332660d3fb08 edfb9de9d5574fda83afe1641331d3ff RY(2*θ) 6e87f4f279254b0b87317099abce9788--edfb9de9d5574fda83afe1641331d3ff ec7785a6304c42c1b33dea05ae99cd5d 2 003e8bc1541a40bbb2d4a094e10c7643 X edfb9de9d5574fda83afe1641331d3ff--003e8bc1541a40bbb2d4a094e10c7643 003e8bc1541a40bbb2d4a094e10c7643--1d135a8203dd41dbba3ecd6555aac966 60c99bd1ca83400f937cb329904cac05 003e8bc1541a40bbb2d4a094e10c7643--60c99bd1ca83400f937cb329904cac05 3b984407025348a6a2b0e568a74ef074 t = Φ 60c99bd1ca83400f937cb329904cac05--3b984407025348a6a2b0e568a74ef074 3b984407025348a6a2b0e568a74ef074--5b45527977304d759347332660d3fb08 d060ce933e6d4f8abbbc59ae1ac01865 c470df31398d4ad6b8909fbdbf8561d8 RZ(cos(Φ)) ec7785a6304c42c1b33dea05ae99cd5d--c470df31398d4ad6b8909fbdbf8561d8 c36464c541814324b7c9cb56670dbe1d c470df31398d4ad6b8909fbdbf8561d8--c36464c541814324b7c9cb56670dbe1d 13dc47a2b5c74d23bf623b1aaa52a150 PHASE(3.142) c36464c541814324b7c9cb56670dbe1d--13dc47a2b5c74d23bf623b1aaa52a150 13dc47a2b5c74d23bf623b1aaa52a150--60c99bd1ca83400f937cb329904cac05 9e950263509d403d8e697efdfacd8954 13dc47a2b5c74d23bf623b1aaa52a150--9e950263509d403d8e697efdfacd8954 9e950263509d403d8e697efdfacd8954--d060ce933e6d4f8abbbc59ae1ac01865

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.