QML Templates

Module name: pennylane.template

This module provides a growing library of templates of common quantum machine learning circuit architectures that can be used to easily build, evaluate, and train more complex quantum machine learning models.

Note

The templates below are constructed out of structured combinations of the quantum operations provided by PennyLane.

As a result, you should follow all the rules of quantum operations when you use templates. For example template functions can only be used within a valid pennylane.qnode.

Examples

For example, you can construct a circuit-centric quantum classifier with the architecture from [R2] on an arbitrary number of wires and with an arbitrary number of blocks by using the template StronglyEntanglingCircuit in the following way:

import pennylane as qml
from pennylane.template import StronglyEntanglingCircuit
from pennylane import numpy as np

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

@qml.qnode(dev)
def circuit(weights, x=None):
    qml.BasisState(x, wires=range(num_wires))
    StronglyEntanglingCircuit(weights, periodic=True, wires=range(num_wires))
    return qml.expval.PauliZ(0)

weights = np.random.randn(num_blocks, num_wires, 3)
print(circuit(weights, x=np.array(np.random.randint(0, 1, num_wires))))

The handy Interferometer() function can be used to construct arbitrary interferometers in terms of elementary Beamsplitter operations, by providing lists of transmittivity and phase angles. PennyLane can then be used to easily differentiate and optimize these parameters:

import pennylane as qml
from pennylane.template import Interferometer
from pennylane import numpy as np

num_wires = 4
dev = qml.device('default.gaussian', wires=num_wires)
num_params = int(num_wires*(num_wires-1)/2)

# initial parameters
r = np.random.rand(num_wires, 2)
theta = np.random.uniform(0, 2*np.pi, num_params)
phi = np.random.uniform(0, 2*np.pi, num_params)

@qml.qnode(dev)
def circuit(theta, phi):
    for w in range(num_wires):
        qml.Squeezing(r[w][0], r[w][1], wires=w)

    Interferometer(theta=theta, phi=phi, wires=range(num_wires))
    return [qml.expval.MeanPhoton(wires=w) for w in range(num_wires)]

print(qml.jacobian(circuit, 0)(theta, phi))

The function CVNeuralNet() implements the continuous-variable neural network architecture from [R3]. Provided with a suitable array of weights, such neural networks can be easily constructed and trained with PennyLane.

Provided templates

StronglyEntanglingCircuit(weights[, …]) A strongly entangling circuit.
StronglyEntanglingCircuitBlock(weights[, …]) An individual block of a strongly entangling circuit.
CVNeuralNet(weights, wires) A CV Quantum Neural Network
CVNeuralNetLayer(theta_1, phi_1, s, theta_2, …) A single layer of a CV Quantum Neural Network
Interferometer(theta, phi, varphi, wires) General linear interferometer.

Code details

StronglyEntanglingCircuit(weights, periodic=True, ranges=None, imprimitive=qml.CNOT, wires)[source]

A strongly entangling circuit.

Constructs the strongly entangling circuit used in the circuit-centric quantum classifier [R2] with len(weights) blocks on the \(N\) wires with the provided weights. Each element of weights must be a an array of size \(3N\).

Parameters:
  • weights (array[float]) – shape (len(weights), len(wires), 3) array of weights
  • periodic (bool) – whether to use periodic boundary conditions when applying imprimitive gates
  • ranges (Sequence[int]) – ranges of the imprimitive gates in the respective blocks
  • imprimitive (pennylane.ops.Operation) – imprimitive gate to use, defaults to CNOT
Keyword Arguments:
 

wires (Sequence[int]) – wires the strongly entangling circuit should act on

StronglyEntanglingCircuitBlock(weights, periodic=True, r=1, imprimitive=qml.CNOT, wires)[source]

An individual block of a strongly entangling circuit.

Parameters:
  • weights (array[float]) – shape (len(wires), 3) array of weights
  • periodic (bool) – whether to use periodic boundary conditions when applying imprimitive gates
  • r (Sequence[int]) – range of the imprimitive gates of this block
  • imprimitive (pennylane.ops.Operation) – Imprimitive gate to use, defaults to CNOT
Keyword Arguments:
 

wires (Sequence[int]) – Wires the block should act on

CVNeuralNet(weights, wires)[source]

A CV Quantum Neural Network

Implements the CV Quantum Neural Network (CVQNN) architecture from [R3] for an arbitrary number of wires and layers.

See CVNeuralNetLayer() for details of the expected format of input parameters.

Parameters:weights (array[array]) – array of arrays of weights for each layer of the CV neural network
Keyword Arguments:
 wires (Sequence[int]) – wires the CVQNN should act on
CVNeuralNetLayer(theta_1, phi_1, s, theta_2, phi_2, r, k, wires)[source]

A single layer of a CV Quantum Neural Network

Implements a single layer from the the CV Quantum Neural Network (CVQNN) architecture of [R3] over \(N\) wires.

Note

The CV neural network architecture includes Kerr operations. Make sure to use a suitable device, such as the strawberryfields.fock device of the PennyLane-SF plugin.

Parameters:
  • theta_1 (array[float]) – length \(N(N-1)/2\) array of transmittivity angles for first interferometer
  • phi_1 (array[float]) – length \(N(N-1)/2\) array of phase angles for first interferometer
  • r (array[float]) – length \(N\) arrays of squeezing amounts for Squeezing operations
  • phi_r (array[float]) – length \(N\) arrays of squeezing angles for Squeezing operations
  • theta_2 (array[float]) – length \(N(N-1)/2\) array of transmittivity angles for second interferometer
  • phi_2 (array[float]) – length \(N(N-1)/2\) array of phase angles for second interferometer
  • a (array[float]) – length \(N\) arrays of displacement magnitudes for Displacement operations
  • phi_a (array[float]) – length \(N\) arrays of displacement angles for Displacement operations
  • k (array[float]) – length \(N\) arrays of kerr parameters for Kerr operations
Keyword Arguments:
 

wires (Sequence[int]) – wires the layer should act on

Interferometer(theta, phi, varphi, wires)[source]

General linear interferometer.

For \(N\) wires, the general interferometer is specified by providing \(N(N-1)\) transmittivity angles \(\theta\) and the same number of phase angles \(\phi\), as well as either \(N-1\) or \(N\) additional rotation parameters \(\varphi\).

For the parametrization of a universal interferometer \(N-1\) such rotation parameters are sufficient. If \(N\) rotation parameters are given, the interferometer is over parametrized, but the resulting circuit is more symmetric, which can be advantageous.

By specifying the keyword argument mesh, the scheme used to implement the interferometer may be adjusted:

  • mesh='rectangular' (default): uses the scheme described in [R4], resulting in a rectangular array of \(N(N-1)/2\) beamsplitters arranged in \(N\) layers and numbered from left to right and top to bottom in each layer. The first beamsplitters acts on wires \(0\) and \(1\).

    ../_images/clements.png


  • mesh='triangular': uses the scheme described in [R5], resulting in a triangular array of \(N(N-1)/2\) beamsplitters arranged in \(2N-3\) layers and numbered from left to right and top to bottom. The first and forth beamsplitters act on wires \(N-1\) and \(N\), the second on \(N-2\) and \(N-1\), and the third on \(N-3\) and \(N-2\), and so on.

    ../_images/reck.png

In both schemes, the network of Beamsplitter operations is followed by \(N\) (or \(N-1\)) local Rotation Operations. In the latter case, the rotation on the last wire is left out.

The rectangular decomposition is generally advantageous, as it has a lower circuit depth (\(N\) vs \(2N-3\)) and optical depth than the triangular decomposition, resulting in reduced optical loss.

Note

The decomposition as formulated in [R4] uses a different convention for a beamsplitter \(T(\theta, \phi)\) than PennyLane, namely:

\[T(\theta, \phi) = BS(\theta, 0) R(\phi)\]

For the universality of the decomposition, the used convention is irrelevant, but for a given set of angles the resulting interferometers will be different.

If an interferometer consistent with the convention from [R4] is needed, the optional keyword argument beamsplitter='clements' can be specified. This will result in each Beamsplitter being preceded by a Rotation and thus increase the number of elementary operations in the circuit.

Parameters:
  • theta (array) – length \(N(N-1)/2\) array of transmittivity angles \(\theta\)
  • phi (array) – length \(N(N-1)/2\) array of phase angles \(\phi\)
  • varphi (array) – length \(N\) or \(N-1\) array of rotation angles \(\varphi\)
Keyword Arguments:
 
  • mesh (string) – the type of mesh to use
  • beamsplitter (str) – if clements, the beamsplitter convention from Clements et al. 2016 (https://dx.doi.org/10.1364/OPTICA.3.001460) is used
  • wires (Sequence[int]) – wires the interferometer should act on