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.8810+0.0000j, 0.0000-0.4731j]])

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.8800+0.0374j,  0.0000+0.0000j,  0.0201-0.4731j,  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_c69207f0258a4f518714b60cd3803645 3726fc79d318422cba7f157a740fba6b 0 0b1b2d66c85f4dc4a528b51f7eb502cc RX(Φ/θ) 3726fc79d318422cba7f157a740fba6b--0b1b2d66c85f4dc4a528b51f7eb502cc 8ca3c04c324949bf97e3534669abc503 1 e9d3ddc019064ab8a0515eb10218a9ae 0b1b2d66c85f4dc4a528b51f7eb502cc--e9d3ddc019064ab8a0515eb10218a9ae 4b50b0336b494d798043e261cfa5452a e9d3ddc019064ab8a0515eb10218a9ae--4b50b0336b494d798043e261cfa5452a 1bc9402183f14b9baee6442154713d3b HamEvo 4b50b0336b494d798043e261cfa5452a--1bc9402183f14b9baee6442154713d3b 8af693f6f56a44e2b3f7b71bc412a72d 1bc9402183f14b9baee6442154713d3b--8af693f6f56a44e2b3f7b71bc412a72d f0bbe0cfbe4140588028adfbfcc6e5b2 fe574e9006524988907a9e108a0340fd RY(2*θ) 8ca3c04c324949bf97e3534669abc503--fe574e9006524988907a9e108a0340fd f15046ce9bb04adf80c2a86739099397 2 d1b1401ba4fd4d959bc237ec0e98f161 X fe574e9006524988907a9e108a0340fd--d1b1401ba4fd4d959bc237ec0e98f161 d1b1401ba4fd4d959bc237ec0e98f161--e9d3ddc019064ab8a0515eb10218a9ae 03608ba327d5406f8734b446dc055a2e d1b1401ba4fd4d959bc237ec0e98f161--03608ba327d5406f8734b446dc055a2e 1231a6cb37184ee089cc1806737398aa t = Φ 03608ba327d5406f8734b446dc055a2e--1231a6cb37184ee089cc1806737398aa 1231a6cb37184ee089cc1806737398aa--f0bbe0cfbe4140588028adfbfcc6e5b2 b7b7547fba26454caabc3ea76a9874a2 fe4860970db84c35ab3f677345145684 RZ(cos(Φ)) f15046ce9bb04adf80c2a86739099397--fe4860970db84c35ab3f677345145684 5a4ebc87b7d84d9bbddbc00ad5bcca53 fe4860970db84c35ab3f677345145684--5a4ebc87b7d84d9bbddbc00ad5bcca53 e876f38f33134b4c89bdbfe49988edba PHASE(3.142) 5a4ebc87b7d84d9bbddbc00ad5bcca53--e876f38f33134b4c89bdbfe49988edba e876f38f33134b4c89bdbfe49988edba--03608ba327d5406f8734b446dc055a2e 1d782cb191c544bdaeeac7c3f4165936 e876f38f33134b4c89bdbfe49988edba--1d782cb191c544bdaeeac7c3f4165936 1d782cb191c544bdaeeac7c3f4165936--b7b7547fba26454caabc3ea76a9874a2

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.