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.9917+0.0000j, 0.0000-0.1288j]])

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.5929-0.5575j,  0.0000+0.0000j, -0.3981-0.4234j,  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_db70276b379a49618f7ab489e25e1f6c fcdfdbaae06c4b3da031ee14d2f50897 0 3e39f90f830843f9b6196fee7bec52ed RX(Φ/θ) fcdfdbaae06c4b3da031ee14d2f50897--3e39f90f830843f9b6196fee7bec52ed 26cf1078f3df4f178ba7f11daa60b1d9 1 c960d9adbc1548449efefbcc2cf01bf3 3e39f90f830843f9b6196fee7bec52ed--c960d9adbc1548449efefbcc2cf01bf3 f3a89d0d213944858c06613004201847 c960d9adbc1548449efefbcc2cf01bf3--f3a89d0d213944858c06613004201847 f877d80af8814660abc2620ae40bde80 HamEvo f3a89d0d213944858c06613004201847--f877d80af8814660abc2620ae40bde80 de53d429351a4a28ac8665ffbf1c5358 f877d80af8814660abc2620ae40bde80--de53d429351a4a28ac8665ffbf1c5358 fd1c05e1dbf8468081ecb807572f4a7e 5a1eb8466fc84e9b9c436e6003d103c8 RY(2*θ) 26cf1078f3df4f178ba7f11daa60b1d9--5a1eb8466fc84e9b9c436e6003d103c8 651e80fc51f641188116b065ca83bc43 2 fcbd3adee644443d91e3b907c7a02ef5 X 5a1eb8466fc84e9b9c436e6003d103c8--fcbd3adee644443d91e3b907c7a02ef5 fcbd3adee644443d91e3b907c7a02ef5--c960d9adbc1548449efefbcc2cf01bf3 289d1d261a8b420f81bbf9408b43fe17 fcbd3adee644443d91e3b907c7a02ef5--289d1d261a8b420f81bbf9408b43fe17 2ab10580d9204edf9e8d475ee8f6c9a2 t = Φ 289d1d261a8b420f81bbf9408b43fe17--2ab10580d9204edf9e8d475ee8f6c9a2 2ab10580d9204edf9e8d475ee8f6c9a2--fd1c05e1dbf8468081ecb807572f4a7e 5a9f6ad4477343219bc55387f5cc04c1 d2c4dc79f454436aa0266c99e1bc0189 RZ(cos(Φ)) 651e80fc51f641188116b065ca83bc43--d2c4dc79f454436aa0266c99e1bc0189 aabd1a5341ff42b68f960bc8d350ee91 d2c4dc79f454436aa0266c99e1bc0189--aabd1a5341ff42b68f960bc8d350ee91 77fc274bd79540449b8589d5be5d1832 PHASE(3.142) aabd1a5341ff42b68f960bc8d350ee91--77fc274bd79540449b8589d5be5d1832 77fc274bd79540449b8589d5be5d1832--289d1d261a8b420f81bbf9408b43fe17 94f3bdf430bf4eb696008218d862a3de 77fc274bd79540449b8589d5be5d1832--94f3bdf430bf4eb696008218d862a3de 94f3bdf430bf4eb696008218d862a3de--5a9f6ad4477343219bc55387f5cc04c1

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.