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 different types of templates, such as Embeddings, Layers, State preparations and Subroutines.
Most templates are complemented by functions that provide an array of random initial parameters.
The following is a gallery of built-in templates provided by PennyLane.
Embedding templates¶
Embeddings encode input features into the quantum state of the circuit. Hence, they take a feature vector as an argument. Embeddings can also depend on trainable parameters, and they may consist of repeated layers.
Layer templates¶
Layer architectures define sequences of trainable gates that are repeated like the layers in a
neural network. Note arbitrary templates or operations can also be layered using the
layer()
function.
State Preparations¶
State preparation templates transform a given state into a sequence of gates preparing that state.
Subroutines¶
Subroutines are sequences of (possibly trainable) gates that do not fulfill the conditions of other templates.
Broadcasting function¶
PennyLane offers a broadcasting function to easily construct templates: broadcast()
takes single quantum operations or other templates and applies them to wires in a specific pattern.
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 initialization functions can be found in the init
module.
Custom templates¶
In addition, custom templates can be created; simply
decorate a Python function that applies quantum gates
with the pennylane.template()
decorator:
@qml.template
def bell_state_preparation(wires):
qml.Hadamard(wires=wires[0])
qml.CNOT(wires=wires)
This registers the template with PennyLane, making it compatible with
functions that act on templates, such as inv()
:
dev = qml.device('default.qubit', wires=2)
@qml.qnode(dev)
def circuit():
qml.inv(bell_state_preparation(wires=[0, 1]))
return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
Adding a new template¶
Consult the Contributing templates page to learn how to grow the templates library by adding your own template to PennyLane.
Contents
Downloads