Hi everyone! Today we’re very glad to announce the release of PennyLane version 0.11.0.
This release comes with two brand new devices, a new QAOA module, as well as an exciting overhaul of the wires system, among other things.
New and improved simulators
There are two brand new devices added to the set of default devices in PennyLane:
-
default.qubit.autograd
, a pure-state qubit simulator written using Autograd, supporting fast gradient calculations using automatic differentiation. -
lightning.qubit
, a new experimental C++ state-vector simulator device. It uses the C++ Eigen library to perform fast linear algebra calculations for simulating quantum state-vector evolution.
lightning.qubit
is currently in beta; it can be installed via pip
:
$ pip install pennylane-lightning
For more details, please see the lightning qubit documentation.
New algorithms and templates
There’s a new Quantum Approximate Optimization Algorithm (QAOA) module providing many new and exciting features for solving optimization problems on quantum devices.
As an example, you can use it to construct and solve a MaxCut problem with QAOA!
Code example
wires = range(3)
graph = Graph([(0, 1), (1, 2), (2, 0)])
cost_h, mixer_h = qaoa.maxcut(graph)
def qaoa_layer(gamma, alpha):
qaoa.cost_layer(gamma, cost_h)
qaoa.mixer_layer(alpha, mixer_h)
def antatz(params, **kwargs):
for w in wires:
qml.Hadamard(wires=w)
# repeat the QAOA layer two times
qml.layer(qaoa_layer, 2, params[0], params[1])
dev = qml.device('default.qubit', wires=len(wires))
cost_function = qml.VQECost(ansatz, cost_h, dev)
There is also a new ApproxTimeEvolution
template added to the PennyLane templates module, which can be used to implement Trotterized time-evolution under a Hamiltonian, as well as a qml.layer
template-constructing function, which takes a unitary, and repeatedly applies it on a set of wires to a given depth.
Code example
def subroutine():
qml.Hadamard(wires=[0])
qml.CNOT(wires=[0, 1])
qml.PauliX(wires=[1])
dev = qml.device('default.qubit', wires=3)
@qml.qnode(dev)
def circuit():
qml.layer(subroutine, 3)
return [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1))]
which creates the following circuit:
>>> circuit()
>>> print(circuit.draw())
0: ──H──╭C──X──H──╭C──X──H──╭C──X──┤ ⟨Z⟩
1: ─────╰X────────╰X────────╰X─────┤ ⟨Z⟩
Wires overhaul
The wires system has been overhauled to become more powerful and user friendly. You can now specify custom wire labels, such as ['anc1', 'anc2', 0, 1, 3]
, where the labels can be strings or numbers, instead of simply using consecutive numbers, as was the case before.
Code example
Custom wire labels are defined by passing a list to the wires argument when creating the device:
>>> dev = qml.device("default.qubit", wires=['anc1', 'anc2', 0, 1, 3])
Quantum operations should then be invoked with these custom wire labels:
>>> @qml.qnode(dev)
>>> def circuit():
… qml.Hadamard(wires='anc2')
… qml.CNOT(wires=['anc1', 3])
… ...
The existing behaviour, in which the number of wires is specified on device initialization, continues to work as usual. This gives a default behaviour where wires are labelled by consecutive integers.
>>> dev = qml.device("default.qubit", wires=5)
Additional features
Other new features include a qml.utils.decompose_hamiltonian function
that can be used to decompose a Hamiltonian into a linear combination of Pauli operators, an integrated device test suite, which can be used to run basic integration tests on core or external devices, and support for returning probabilities from photonic QNodes.
The full release notes are available at Release notes — PennyLane 0.27.0 documentation.
As always, this release would not have been possible without all the help from our contributors:
@jmarrazola, @Tom_Bromley, Jack Ceroni, @Alain_Delgado_Gran, Shadab Hussain, @theodor, @josh, @nathan, @Maria_Schuld, @antalszava, @nvitucci