New features since last release
New and improved simulators
-
Added a new device,
default.qubit.autograd
, a pure-state qubit simulator written using Autograd. This device supports classical backpropagation (diff_method="backprop"
); this can be faster than the parameter-shift rule for computing quantum gradients when the number of parameters to be optimized is large. (#721)>>> dev = qml.device("default.qubit.autograd", wires=1) >>> @qml.qnode(dev, diff_method="backprop") ... def circuit(x): ... qml.RX(x[1], wires=0) ... qml.Rot(x[0], x[1], x[2], wires=0) ... return qml.expval(qml.PauliZ(0)) >>> weights = np.array([0.2, 0.5, 0.1]) >>> grad_fn = qml.grad(circuit) >>> print(grad_fn(weights)) array([-2.25267173e-01, -1.00864546e+00, 6.93889390e-18])
See the device documentation for more details.
-
A new experimental C++ state-vector simulator device is now available,
lightning.qubit
. 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 viapip
:$ pip install pennylane-lightning
Once installed, it can be used as a PennyLane device:
>>> dev = qml.device("lightning.qubit", wires=2)
For more details, please see the lightning qubit documentation.
New algorithms and templates
-
Added built-in QAOA functionality via the new
qml.qaoa
module. (#712) (#718) (#741) (#720)This includes the following features:
-
New
qml.qaoa.x_mixer
andqml.qaoa.xy_mixer
functions for defining Pauli-X and XY mixer Hamiltonians. -
MaxCut: The
qml.qaoa.maxcut
function allows easy construction of the cost Hamiltonian and recommended mixer Hamiltonian for solving the MaxCut problem for a supplied graph. -
Layers:
qml.qaoa.cost_layer
andqml.qaoa.mixer_layer
take cost and mixer Hamiltonians, respectively, and apply the corresponding QAOA cost and mixer layers to the quantum circuit
For example, using PennyLane to construct and solve a MaxCut problem with QAOA:
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)
-
-
Added an
ApproxTimeEvolution
template to the PennyLane templates module, which can be used to implement Trotterized time-evolution under a Hamiltonian. (#710) -
Added a
qml.layer
template-constructing function, which takes a unitary, and repeatedly applies it on a set of wires to a given depth. (#723)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))]
This creates the following circuit:
>>> circuit() >>> print(circuit.draw()) 0: ──H──╭C──X──H──╭C──X──H──╭C──X──┤ ⟨Z⟩ 1: ─────╰X────────╰X────────╰X─────┤ ⟨Z⟩
-
Added the
qml.utils.decompose_hamiltonian
function. This function can be used to decompose a Hamiltonian into a linear combination of Pauli operators. (#671)>>> A = np.array( ... [[-2, -2+1j, -2, -2], ... [-2-1j, 0, 0, -1], ... [-2, 0, -2, -1], ... [-2, -1, -1, 0]]) >>> coeffs, obs_list = decompose_hamiltonian(A)
New device features
-
It is now possible to specify custom wire labels, such as
['anc1', 'anc2', 0, 1, 3]
, where the labels can be strings or numbers. (#666)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)
-
An integrated device test suite has been added, which can be used to run basic integration tests on core or external devices. (#695) (#724) (#733)
The test can be invoked against a particular device by calling the
pl-device-test
command line program:$ pl-device-test --device=default.qubit --shots=1234 --analytic=False
If the tests are run on external devices, the device and its dependencies must be installed locally. For more details, please see the plugin test documentation.
Improvements
-
Added support for TensorFlow 2.3 and PyTorch 1.6. (#725)
-
Returning probabilities is now supported from photonic QNodes. As with qubit QNodes, photonic QNodes returning probabilities are end-to-end differentiable. (#699)
>>> dev = qml.device("strawberryfields.fock", wires=2, cutoff_dim=5) >>> @qml.qnode(dev) ... def circuit(a): ... qml.Displacement(a, 0, wires=0) ... return qml.probs(wires=0) >>> print(circuit(0.5)) [7.78800783e-01 1.94700196e-01 2.43375245e-02 2.02812704e-03 1.26757940e-04]
Breaking changes
- The
pennylane.plugins
andpennylane.beta.plugins
folders have been renamed topennylane.devices
andpennylane.beta.devices
, to reflect their content better. (#726)
Bug fixes
- The PennyLane interface conversion functions can now convert QNodes with pre-existing interfaces. (#707)
Documentation
- The interfaces section of the documentation has been renamed to 'Interfaces and training', and updated with the latest variable handling details. (#753)
Contributors
This release contains contributions from (in alphabetical order):
Juan Miguel Arazzola, Thomas Bromley, Jack Ceroni, Alain Delgado Gran, Shadab Hussain, Theodor Isacsson, Josh Izaac, Nathan Killoran, Maria Schuld, Antal Száva, Nicola Vitucci.