Templates

PennyLane provides a growing library of pre-coded templates of common variational circuit architectures that can be used to easily build, evaluate, and train more complex models. In the literature, such architectures are commonly known as an ansatz.

Note

Templates are constructed out of structured combinations of the quantum operations provided by PennyLane. This means that template functions can only be used within a valid QNode.

PennyLane conceptually distinguishes two types of templates, layer architectures and input embeddings. Most templates are complemented by functions that provide an array of random initial parameters .

An example of how to use templates is the following:

import pennylane as qml
from pennylane.templates.embeddings import AngleEmbedding
from pennylane.templates.layers import StronglyEntanglingLayers
from pennylane.init import strong_ent_layers_uniform

dev = qml.device('default.qubit', wires=2)

@qml.qnode(dev)
def circuit(weights, x=None):
    AngleEmbedding(x, [0,1])
    StronglyEntanglingLayers(weights, wires=[0,1])
    return qml.expval(qml.PauliZ(0))

init_weights = strong_ent_layers_uniform(n_layers=3, n_wires=2)
print(circuit(init_weights, x=[1., 2.]))

Here, we used the embedding template AngleEmbedding() together with the layer template StronglyEntanglingLayers(), and the uniform parameter initialization strategy strong_ent_layers_uniform().

Layer templates

Layer architectures define sequences of trainable gates that are repeated like the layers in a neural network.

The following layer templates are available:

CVNeuralNetLayers A sequence of layers of a continuous-variable quantum neural network, as specified in arXiv:1806.06871.
RandomLayers Layers of randomly chosen single qubit rotations and 2-qubit entangling gates, acting on randomly chosen qubits.
StronglyEntanglingLayers Layers consisting of single qubit rotations and entanglers, inspired by the circuit-centric classifier design arXiv:1804.00633.

Embedding templates

Embeddings encode input features into the quantum state of the circuit. Hence, they take a feature vector as an argument. These embeddings can also depend on trainable parameters and be repeated.

The following embedding templates are available:

AmplitudeEmbedding Encodes \(2^n\) features into the amplitude vector of \(n\) qubits.
BasisEmbedding Encodes \(n\) binary features into a basis state of \(n\) qubits.
AngleEmbedding Encodes \(N\) features into the rotation angles of \(n\) qubits, where \(N \leq n\).
SqueezingEmbedding Encodes \(N\) features into the squeezing amplitudes \(r \geq 0\) or phases \(\phi \in [0, 2\pi)\) of \(M\) modes, where \(N\leq M\).
DisplacementEmbedding Encodes \(N\) features into the displacement amplitudes \(r\) or phases \(\phi\) of \(M\) modes,

Subroutines

Subroutines are simply a collection of (trainable) gates.

The following subroutines are available:

Interferometer General linear interferometer, an array of beamsplitters and phase shifters.

Parameter initializations

Each trainable template has dedicated functions in the pennylane.init module, which generate randomly initialized arrays for the trainable parameters. For example, random_layers_uniform() can be used together with the template RandomLayers():

import pennylane as qml
from pennylane.templates import RandomLayers
from pennylane.init import random_layers_uniform

dev = qml.device('default.qubit', wires=3)

@qml.qnode(dev)
def circuit(weights):
    RandomLayers(weights=weights, wires=[0, 2])
    return qml.expval(qml.PauliZ(0))

init_pars = random_layers_uniform(n_layers=3, n_wires=2)
circuit(init_pars)

Templates that take more than one parameter array require several initialization functions:

from pennylane.templates import Interferometer
from pennylane.init import (interferometer_theta_uniform,
                            interferometer_phi_uniform,
                            interferometer_varphi_normal)

dev = qml.device('default.gaussian', wires=3)

@qml.qnode(dev)
def circuit(theta, phi, varphi):
    Interferometer(theta=theta, phi=phi, varphi=varphi, wires=[0, 2])
    return qml.expval(qml.X(0))

init_theta = interferometer_theta_uniform(n_wires=2)
init_phi = interferometer_phi_uniform(n_wires=2)
init_varphi = interferometer_varphi_normal(n_wires=2)

circuit(init_theta, init_phi, init_varphi)

For templates with multiple parameters, initializations that return a list of all parameter arrays at once are provided, and can be conveniently used in conjunction with the unpacking operator *:

from pennylane.templates import Interferometer
from pennylane.init import interferometer_all

dev = qml.device('default.gaussian', wires=3)

@qml.qnode(dev)
def circuit(*pars):
    Interferometer(*pars, wires=[0, 2])
    return qml.expval(qml.X(0))

init_pars = interferometer_all(n_wires=2)

circuit(*init_pars)

Initial parameters can be converted to Torch or TensorFlow tensors, which can be used in the respective interfaces.

import torch
import tensorflow as tf
from pennylane.init import strong_ent_layers_normal

init_pars = strong_ent_layers_normal(n_layers=3, n_wires=2)
init_torch = torch.tensor(init_pars)
init_tf = tf.Variable(init_pars)

The following initialization functions are available:

Strongly entangling circuit

strong_ent_layers_uniform Creates a parameter array for StronglyEntanglingLayers(), drawn from a uniform distribution.
strong_ent_layers_normal Creates a parameter array for StronglyEntanglingLayers(), drawn from a normal distribution.

Random circuit

random_layers_uniform Creates a parameter array for RandomLayers(), drawn from a uniform distribution.
random_layers_normal Creates a parameter array for RandomLayers(), drawn from a normal distribution.

Continuous-variable quantum neural network

cvqnn_layers_all Creates a list of all eleven parameter arrays for CVNeuralNetLayers().
cvqnn_layers_theta_uniform Creates a parameter array for the theta input to the interferometers of CVNeuralNetLayers().
cvqnn_layers_theta_normal Creates a parameter array for the theta input to the interferometers of CVNeuralNetLayers().
cvqnn_layers_phi_uniform Creates a parameter array for the phi input to the interferometers of CVNeuralNetLayers().
cvqnn_layers_phi_normal Creates a parameter array for the phi input to the interferometers of CVNeuralNetLayers().
cvqnn_layers_varphi_uniform Creates a parameter array for the varphi input to the interferometers of CVNeuralNetLayers().
cvqnn_layers_varphi_normal Creates a parameter array for the varphi input to the interferometers of CVNeuralNetLayers().
cvqnn_layers_r_uniform Creates a parameter array for the squeezing amplitude r of CVNeuralNetLayers().
cvqnn_layers_r_normal Creates a parameter array for the squeezing amplitude r of CVNeuralNetLayers().
cvqnn_layers_phi_r_uniform Creates a parameter array for the squeezing phase phi_r of CVNeuralNetLayers().
cvqnn_layers_phi_r_normal Creates a parameter array for the squeezing phase phi_r of CVNeuralNetLayers().
cvqnn_layers_a_uniform Creates a parameter array for the displacement amplitude a of CVNeuralNetLayers().
cvqnn_layers_a_normal Creates a parameter array for the displacement amplitude a of CVNeuralNetLayers().
cvqnn_layers_phi_a_uniform Creates a parameter array for the displacement phase phi_a of CVNeuralNetLayers().
cvqnn_layers_phi_a_normal Creates a parameter array for the displacement phase phi_a of CVNeuralNetLayers().
cvqnn_layers_kappa_uniform Creates a parameter array for the kerr parameter kappa of CVNeuralNetLayers().
cvqnn_layers_kappa_normal Creates a parameter array for the kerr parameter kappa of CVNeuralNetLayers().

Interferometer

interferometer_all Creates a list of arrays for the three initial parameters of Interferometer(), all drawn from a uniform distribution with interval \([0, 2\pi]\).
interferometer_theta_uniform Creates a parameter array for the theta input of Interferometer(), drawn from a uniform distribution.
interferometer_theta_normal Creates a parameter array for the theta input of Interferometer(), drawn from a normal distribution.
interferometer_phi_uniform Creates a parameter array for the phi input of Interferometer(), drawn from a uniform distribution.
interferometer_phi_normal Creates a parameter array for the phi input of Interferometer(), drawn from a normal distribution.
interferometer_varphi_uniform Creates a parameter array for the varphi input of Interferometer(), drawn from a uniform distribution.
interferometer_varphi_normal Creates a parameter array for the varphi input of Interferometer(), drawn from a normal distribution.