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.9163+0.0000j, 0.0000-0.4005j]])

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.2722+0.3028j,  0.0000+0.0000j,  0.6793-0.6106j,  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_84aa24cacaa2446796fe15ba6e70ec5a 3a88c97a2e874cc6852ebf8062fbc9d4 0 b9a1928498fe40778bb4acda0b0b51ec RX(Φ/θ) 3a88c97a2e874cc6852ebf8062fbc9d4--b9a1928498fe40778bb4acda0b0b51ec 8c017822cf1d4c2f8bd7a8cd9d09758a 1 e32fb2baf8594dccaa47f6f707852797 b9a1928498fe40778bb4acda0b0b51ec--e32fb2baf8594dccaa47f6f707852797 394142738eff4c20a5c44652d9b7f229 e32fb2baf8594dccaa47f6f707852797--394142738eff4c20a5c44652d9b7f229 92070dc5578140769f70aff06f102f73 HamEvo 394142738eff4c20a5c44652d9b7f229--92070dc5578140769f70aff06f102f73 9e59698359c9486fabafab97394d4231 92070dc5578140769f70aff06f102f73--9e59698359c9486fabafab97394d4231 b83dadae2f8b4b0e9ee5cfa02dd2856a 1f5d9288867b44f6a5c251a8ab728f7f RY(2*θ) 8c017822cf1d4c2f8bd7a8cd9d09758a--1f5d9288867b44f6a5c251a8ab728f7f 2f0342b561204d3a938c9888e73923bb 2 107d4e7af17b49f3bc550b8edfaa89cc X 1f5d9288867b44f6a5c251a8ab728f7f--107d4e7af17b49f3bc550b8edfaa89cc 107d4e7af17b49f3bc550b8edfaa89cc--e32fb2baf8594dccaa47f6f707852797 e8b860b7a15c47bea1e3e5af11b5d607 107d4e7af17b49f3bc550b8edfaa89cc--e8b860b7a15c47bea1e3e5af11b5d607 a92ab77f317b4f4fbf3f72c33f51a81f t = Φ e8b860b7a15c47bea1e3e5af11b5d607--a92ab77f317b4f4fbf3f72c33f51a81f a92ab77f317b4f4fbf3f72c33f51a81f--b83dadae2f8b4b0e9ee5cfa02dd2856a 84d5cca5d46a48be8051271b05937500 0f69709ed55040ca9da6905544448b71 RZ(cos(Φ)) 2f0342b561204d3a938c9888e73923bb--0f69709ed55040ca9da6905544448b71 556d94262b744dcca1232f7871a9b7de 0f69709ed55040ca9da6905544448b71--556d94262b744dcca1232f7871a9b7de 4d069bc76822435194cc1d64a595d4cb PHASE(3.142) 556d94262b744dcca1232f7871a9b7de--4d069bc76822435194cc1d64a595d4cb 4d069bc76822435194cc1d64a595d4cb--e8b860b7a15c47bea1e3e5af11b5d607 c173468176dc42d38e4a3df7bbbe004c 4d069bc76822435194cc1d64a595d4cb--c173468176dc42d38e4a3df7bbbe004c c173468176dc42d38e4a3df7bbbe004c--84d5cca5d46a48be8051271b05937500

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.