PennyLane-Cirq Plugin

Release

0.37.0-dev

The PennyLane-Cirq plugin integrates the Cirq quantum computing framework with PennyLane’s quantum machine learning capabilities.

PennyLane is a cross-platform Python library for quantum machine learning, automatic differentiation, and optimization of hybrid quantum-classical computations.

Cirq is a software library for quantum computing.

Once Pennylane-Cirq is installed, the provided Cirq devices can be accessed straight away in PennyLane, without the need to import any additional packages.


You can also try it out using any of the qubit based demos from the PennyLane documentation, for example the tutorial on qubit rotation. Simply replace 'default.qubit' with the 'cirq.simulator' device

dev = qml.device('cirq.simulator', wires=XXX)

Installation

This plugin requires Python version 3.9 or above, as well as PennyLane and Cirq. Installation of this plugin, as well as all dependencies, can be done using pip:

$ pip install pennylane-cirq

Alternatively, you can install PennyLane-Cirq from the source code by navigating to the top directory and running:

$ python setup.py install

Dependencies

PennyLane-Cirq requires the following libraries be installed:

as well as the following Python packages:

To use the qsim and qsimh devices, the qsim-Cirq interface qsimcirq is required:

It can be installed using pip:

$ pip install qsimcirq

If you currently do not have Python 3 installed, we recommend Anaconda for Python 3, a distributed version of Python packaged for scientific computation.

Tests

To test that the PennyLane-Cirq plugin is working correctly you can run

$ make test

in the source folder.

Documentation

To build the HTML documentation, go to the top-level directory and run:

$ make docs

The documentation can then be found in the doc/_build/html/ directory.

Support

If you are having issues, please let us know by posting the issue on our Github issue tracker, or by asking a question in the forum.

Simulator device

You can instantiate the device in PennyLane as follows:

import pennylane as qml

dev = qml.device('cirq.simulator', wires=2)

This device can then be used just like other devices for the definition and evaluation of QNodes within PennyLane. A simple quantum function that returns the expectation value of a measurement and depends on three classical input parameters would look like:

@qml.qnode(dev)
def circuit(x, y, z):
    qml.RZ(z, wires=[0])
    qml.RY(y, wires=[0])
    qml.RX(x, wires=[0])
    qml.CNOT(wires=[0, 1])
    return qml.expval(qml.PauliZ(wires=1))

You can then execute the circuit like any other function to get the quantum mechanical expectation value.

circuit(0.2, 0.1, 0.3)

Device options

Cirq has different ways of defining qubits, e.g., LineQubit or GridQubit. The Cirq device therefore accepts an additional argument qubits=None that you can use to define your own qubits and give them to the device as a list.

import cirq

qubits = [
  cirq.GridQubit(0, 0),
  cirq.GridQubit(0, 1),
  cirq.GridQubit(1, 0),
  cirq.GridQubit(1, 1),
]

dev = qml.device("cirq.simulator", wires=4, qubits=qubits)

The wire of each qubit corresponds to its index in the qubit list. In the above example, the wire 2 corresponds to cirq.GridQubit(1, 0).

If no qubits are given, the plugin will create an array of LineQubit instances.

Custom simulators

The simulator device can also be instantiated using an optional custom simulator object:

import pennylane as qml
import cirq

sim = cirq.Simulator()
dev = qml.device("cirq.simulator", wires=2, simulator=sim)

If the simulator argument is not provided, the device will by default create a cirq.Simulator simulator.

Supported operations

The cirq.simulator device supports all PennyLane operations and observables.

Mixed Simulator Device

You can instantiate the mixed-state simulator device in PennyLane as follows:

import pennylane as qml

dev = qml.device('cirq.mixedsimulator', wires=2)

This device can then be used just like other devices for the definition and evaluation of QNodes within PennyLane. Unlike the cirq.simulator backend, this device also supports several of Cirq’s custom non-unitary channels, e.g., BitFlip or Depolarize.

from pennylane_cirq import ops

@qml.qnode(dev)
def circuit(x, p, q):
    qml.RX(x, wires=[0])
    ops.BitFlip(p, wires=[0])
    ops.Depolarize(q, wires=[1])
    qml.CNOT(wires=[0, 1])
    return qml.expval(qml.PauliZ(wires=1))

circuit(0.2, 0.1, 0.3)

This device stores the internal state of the quantum simulation as a density matrix. This has additional memory overhead compared to pure-state simulation, but allows for additional channels to be performed. The density matrix can be accessed after a circuit execution using dev.state.

Device options

Cirq has different ways of defining qubits, e.g., LineQubit or GridQubit. The Cirq device therefore accepts an additional argument qubits=None that you can use to define your own qubits and give them to the device as a list.

import cirq

qubits = [
  cirq.GridQubit(0, 0),
  cirq.GridQubit(0, 1),
  cirq.GridQubit(1, 0),
  cirq.GridQubit(1, 1),
]

dev = qml.device("cirq.mixedsimulator", wires=4, qubits=qubits)

The wire of each qubit corresponds to its index in the qubit list. In the above example, the wire 2 corresponds to cirq.GridQubit(1, 0).

If no qubits are given, the plugin will create an array of LineQubit instances.

Supported operations

The cirq.mixedsimulator device supports all PennyLane operations and observables.

It also supports the following non-unitary channels from Cirq (found in pennylane_cirq.ops): BitFlip, PhaseFlip, PhaseDamp, AmplitudeDamp, and Depolarize.

The qsim device

The qsim circuit simulator package provides two additional circuit simulators that can be used with PennyLane-Cirq:

  • qsim, a Schrödinger full state-vector simulator

  • qsimh, a hybrid Schrödinger-Feynman simulator. This simulator cuts the qubit lattice into two parts; each part is individually simulated using qsim, with Feynman-style path summation used to return the final result. Compared to full state-vector simulation, qsimh reduces memory requirements, at the expense of an increased runtime.

For further details see the qsim website.

For a large number of qubits, these simulators are considerably faster than the Cirq simulator:

_images/qsim_bench.png

In order to use these devices, the qsimcirq package must first be installed:

pip install qsimcirq

You can instantiate the qsim device in PennyLane as follows:

import pennylane as qml

dev = qml.device('cirq.qsim', wires=2)

This device can then be used just like other devices for the evaluation of QNodes within PennyLane. A simple quantum function that returns the expectation value of a measurement and depends on three classical input parameters would look like:

@qml.qnode(dev)
def circuit(x, y, z):
    qml.RZ(z, wires=[0])
    qml.RY(y, wires=[0])
    qml.RX(x, wires=[0])
    qml.CNOT(wires=[0, 1])
    return qml.expval(qml.PauliZ(wires=1))

You can then execute the circuit like any other function to get the quantum mechanical expectation value:

circuit(0.2, 0.1, 0.3)

The qsimh device can be loaded similarly, with the addition of the keyword argument qsimh_options as described below.

Device options

qsim and qsimh use the same method of defining qubits as Cirq, e.g., LineQubit or GridQubit. As with the Cirq device, the qsim and qsimh devices therefore accept an additional argument qubits that can be used to define your own qubits and pass them to the device as a list.

import cirq

qubits = [
  cirq.GridQubit(0, 0),
  cirq.GridQubit(0, 1),
  cirq.GridQubit(1, 0),
  cirq.GridQubit(1, 1),
]

dev = qml.device("cirq.qsim", wires=4, qubits=qubits)

The wire of each qubit corresponds to its index in the qubit list. In the above example, the wire 2 corresponds to cirq.GridQubit(1, 0).

If no qubits are given, the plugin will create an array of LineQubit instances.

qsimh options

qsimh requires specific options to be set for the simulator. These can be passed by the positional argument qsimh_options. See the qsimh usage documentation for further details.

import cirq

qubits = [
  cirq.GridQubit(0, 0),
  cirq.GridQubit(0, 1),
  cirq.GridQubit(1, 0),
  cirq.GridQubit(1, 1),
]

qsimh_options = {
    'k': [0],
    'w': 0,
    'p': 0,
    'r': 2
}

dev = qml.device("cirq.qsimh", wires=4, qsimh_options=qsimh_options, qubits=qubits)

Supported operations

The cirq.qsim and cirq.qsimh devices support most PennyLane operations and observables, with the exceptions of most adjoint operations and QubitUnitary gates on 3 or more qubits.

For state preparation qsim relies on decomposing BasisState into a set of PauliX gates and QubitStateVector via Möttönen state preparation.

Pasqal Device

You can instantiate a simulator for Pasqal’s neutral-atom devices in PennyLane as follows:

import pennylane as qml

dev = qml.device("cirq.pasqal", wires=2, control_radius=1.5)

This device can then be used just like other devices for the definition and evaluation of QNodes within PennyLane.

The Pasqal device supports unique features of Pasqal’s quantum computing hardware provided via Cirq, namely the ThreeDQubit and the notion of a control_radius.

from cirq_pasqal import ThreeDQubit
qubits = [ThreeDQubit(x, y, z)
          for x in range(2)
          for y in range(2)
          for z in range(2)]
dev = qml.device("cirq.pasqal", control_radius = 2., qubits=qubits, wires=len(qubits))

@qml.qnode(dev)
def circuit(x):
    qml.RX(x, wires=[0])
    qml.CNOT(wires=[0, 1])
    return qml.expval(qml.PauliZ(wires=1))

circuit(0.3)

Note that if not specified, ThreeDGridQubits are automatically arranged in a linear arrangement along the first coordinate axis, separated by a distance of control_radius / 2. That is, (0, 0, 0), (control_radius/2, 0, 0), (control_radius, 0, 0).

For more details about Pasqal devices, consult the Cirq docs.

pennylane-cirq

This section contains the API documentation for the PennyLane-Cirq plugin.

Warning

Unless you are a PennyLane plugin developer, you likely do not need to use these classes and functions directly.

See the overview page for more details using the available Cirq devices with PennyLane.

Plugin overview

Classes

AmplitudeDamp(*params[, wires, id])

Cirq amplitude_damp operation.

BitFlip(*params[, wires, id])

Cirq bit_flip operation.

Depolarize(*params[, wires, id])

Cirq depolarize operation.

MixedStateSimulatorDevice(wires[, shots, qubits])

Cirq mixed-state simulator device for PennyLane.

PasqalDevice(wires, control_radius[, shots, ...])

Cirq Pasqal device for PennyLane.

PhaseDamp(*params[, wires, id])

Cirq phase_damp operation.

PhaseFlip(*params[, wires, id])

Cirq phase_flip operation.

SimulatorDevice(wires[, shots, qubits, ...])

Cirq simulator device for PennyLane.

Class Inheritance Diagram

Inheritance diagram of pennylane_cirq.ops.AmplitudeDamp, pennylane_cirq.ops.BitFlip, pennylane_cirq.ops.Depolarize, pennylane_cirq.simulator_device.MixedStateSimulatorDevice, pennylane_cirq.pasqal_device.PasqalDevice, pennylane_cirq.ops.PhaseDamp, pennylane_cirq.ops.PhaseFlip, pennylane_cirq.simulator_device.SimulatorDevice